From 868e907bdec033e993e02a6208d6ec6c96402e4f Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Wed, 20 Dec 2017 00:28:36 +0100 Subject: day18 --- day18 | 41 +++++++++++++++++ day18.cc | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 day18 create mode 100644 day18.cc diff --git a/day18 b/day18 new file mode 100644 index 0000000..dd5f7cc --- /dev/null +++ b/day18 @@ -0,0 +1,41 @@ +set i 31 +set a 1 +mul p 17 +jgz p p +mul a 2 +add i -1 +jgz i -2 +add a -1 +set i 127 +set p 618 +mul p 8505 +mod p a +mul p 129749 +add p 12345 +mod p a +set b p +mod b 10000 +snd b +add i -1 +jgz i -9 +jgz a 3 +rcv b +jgz b -1 +set f 0 +set i 126 +rcv a +rcv b +set p a +mul p -1 +add p b +jgz p 4 +snd a +set a b +jgz 1 3 +snd b +set f 1 +add i -1 +jgz i -11 +snd a +jgz f -16 +jgz a -19 diff --git a/day18.cc b/day18.cc new file mode 100644 index 0000000..8a73064 --- /dev/null +++ b/day18.cc @@ -0,0 +1,156 @@ +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +int part; +int p1 = 0; +int p2 = 0; + +struct cpu; + +struct insn { + virtual void run(cpu &) = 0; + virtual bool stalled(cpu &) { return false; } +}; + +struct cpu { + int64_t reg[256]; + const vector> &insns; + vector>::const_iterator ip; + deque &sndq, &rcvq; + int id; + + cpu(const vector> &insns, + deque &sq, deque &rq, int id=0) : + reg{0}, insns{insns}, ip{cbegin(insns)}, sndq{sq}, rcvq{rq}, + id{id} + { + reg[(uint8_t)'p'] = id; + } + + void step() { (*ip++)->run(*this); } + bool done() { return ip == cend(insns); } + bool stalled() { return (*ip)->stalled(*this); } +}; + +struct arg { + virtual long operator()(cpu &) = 0; +}; + +struct const_arg : arg { + long l; + const_arg(long l) : l{l} {} + long operator()(cpu &) { return l; } +}; + +struct reg_arg : arg { + uint8_t r; + reg_arg(uint8_t r) : r{r} {} + long operator()(cpu &c) { return c.reg[r]; } +}; + +unique_ptr +parse(string s) { + if (islower(s[0])) + return make_unique(uint8_t(s[0])); + else + return make_unique(stol(s)); +} + +struct binop : public insn { +public: + uint8_t r; + unique_ptr a; + binop(string &s) : r(s[4]), a{parse(&s[6])} {}; +}; + +struct opset : public binop { using binop::binop; + void run(cpu &c) { c.reg[r] = (*a)(c); } +}; +struct opadd : public binop { using binop::binop; + void run(cpu &c) { c.reg[r] += (*a)(c); } +}; +struct opmul : public binop { using binop::binop; + void run(cpu &c) { c.reg[r] *= (*a)(c); } +}; +struct opmod : public binop { using binop::binop; + void run(cpu &c) { c.reg[r] %= (*a)(c); } +}; +struct opjgz : public insn { + unique_ptr a1, a2; + opjgz(string &s) : a1{parse(&s[4])}, a2{parse(&s[6])} {} + void run(cpu &c) { if ((*a1)(c) > 0) advance(c.ip, (*a2)(c) - 1); } +}; +struct opsnd : public insn { + unique_ptr a; + opsnd(string &s) : a{parse(&s[4])} {} + void run(cpu &c) { + if (part == 1) { + p1 = (*a)(c); + } else { + if (c.id == 1) + p2++; + c.sndq.push_back((*a)(c)); + } + } +}; +struct oprcv : public insn { + uint8_t r; + oprcv(string &s) : r(s[4]) {} + void run(cpu &c) { + if (part == 2) { + if (empty(c.rcvq)) { + --c.ip; + } else { + c.reg[r] = c.rcvq.front(); + c.rcvq.pop_front(); + } + } + } + bool stalled(cpu &c) { return part == 1 ? c.reg[r] > 0 : empty(c.rcvq); } +}; + +int +main() { + string line; + vector> code; + + while (getline(cin, line)) { + auto is_op = [&](string p){ + return equal(begin(p), end(p), begin(line)); + }; + + insn* op; + if (is_op("set")) op = new opset{line}; + else if (is_op("add")) op = new opadd{line}; + else if (is_op("mul")) op = new opmul{line}; + else if (is_op("mod")) op = new opmod{line}; + else if (is_op("jgz")) op = new opjgz{line}; + else if (is_op("snd")) op = new opsnd{line}; + else if (is_op("rcv")) op = new oprcv{line}; + code.emplace_back(op); + } + + part = 1; + + deque _; + for (cpu c{code, _, _}; !c.done() && !c.stalled(); c.step()) + ; + + part = 2; + + deque q01, q10; + for (cpu c0{code, q01, q10, 0}, + c1{code, q10, q01, 1}; + !c0.done() && !c1.done() && !(c0.stalled() && c1.stalled()); + c0.step(), c1.step()) + ; + + cout << p1 << endl << p2 << endl; // 3423 7493 +} -- cgit 1.4.1