diff options
author | Leah Neukirchen <leah@vuxu.org> | 2017-12-20 00:28:36 +0100 |
---|---|---|
committer | Leah Neukirchen <leah@vuxu.org> | 2017-12-20 00:28:36 +0100 |
commit | 868e907bdec033e993e02a6208d6ec6c96402e4f (patch) | |
tree | a07d6e5443f491821e8affaea6116449d81b3a33 | |
parent | 301c154d3eaa03a673f0ced1c94a623fe9d6e39e (diff) | |
download | adventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.tar.gz adventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.tar.xz adventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.zip |
day18
-rw-r--r-- | day18 | 41 | ||||
-rw-r--r-- | day18.cc | 156 |
2 files changed, 197 insertions, 0 deletions
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 <iostream> +#include <string> +#include <algorithm> +#include <variant> +#include <vector> +#include <deque> +#include <memory> + +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<unique_ptr<insn>> &insns; + vector<unique_ptr<insn>>::const_iterator ip; + deque<uint64_t> &sndq, &rcvq; + int id; + + cpu(const vector<unique_ptr<insn>> &insns, + deque<uint64_t> &sq, deque<uint64_t> &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<arg> +parse(string s) { + if (islower(s[0])) + return make_unique<reg_arg>(uint8_t(s[0])); + else + return make_unique<const_arg>(stol(s)); +} + +struct binop : public insn { +public: + uint8_t r; + unique_ptr<arg> 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<arg> 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<arg> 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<unique_ptr<insn>> 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<uint64_t> _; + for (cpu c{code, _, _}; !c.done() && !c.stalled(); c.step()) + ; + + part = 2; + + deque<uint64_t> 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 +} |