#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 }