aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2017-12-20 00:28:36 +0100
committerLeah Neukirchen <leah@vuxu.org>2017-12-20 00:28:36 +0100
commit868e907bdec033e993e02a6208d6ec6c96402e4f (patch)
treea07d6e5443f491821e8affaea6116449d81b3a33
parent301c154d3eaa03a673f0ced1c94a623fe9d6e39e (diff)
downloadadventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.tar.gz
adventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.tar.xz
adventofcode2017-868e907bdec033e993e02a6208d6ec6c96402e4f.zip
day18
-rw-r--r--day1841
-rw-r--r--day18.cc156
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
+}