-
Notifications
You must be signed in to change notification settings - Fork 0
/
puzzle_18_2.cc
140 lines (122 loc) · 4.07 KB
/
puzzle_18_2.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#include <iomanip>
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <deque>
#include <map>
// snd X plays a sound with a frequency equal to the value of X.
// set X Y sets register X to the value of Y.
// add X Y increases register X by the value of Y.
// mul X Y sets register X to the result of multiplying the value contained in
// register X by the value of Y.
// mod X Y sets register X to the remainder of dividing the value contained in
// register X by the value of Y (that is, it sets X to the result of X modulo Y).
// rcv X recovers the frequency of the last sound played, but only when the
// value of X is not zero. (If it is zero, the command does nothing.)
// jgz X Y jumps with an offset of the value of Y, but only if the value of X
// is greater than zero. (An offset of 2 skips the next instruction, an offset
// of -1 jumps to the previous instruction, and so on.)
using Program = std::vector<std::string>;
using Queue = std::deque<int>;
struct Registers {
using Storage = std::map<std::string, long>;
using iterator = Storage::iterator;
Registers(int pid) : registers{{"p", pid}}
{}
iterator regOrVal(const std::string& input)
{
// std::cout << "input: " << input << " is ";
if (input[0] == '-' || (input[0] >= '0' && input[0] <= '9')) {
auto it = registers.insert({input, atoi(&input[0])}).first;
// std::cout << "val: " << it->second << "\n";
return it;
} else {
auto it = registers.insert({input, 0}).first;
// std::cout << "reg: " << it->second << "\n";
return it;
}
}
private:
Storage registers;
};
struct Context {
Context(const Program& _program, int _pid, Queue& _rq, Queue& _wq)
: program(_program)
, registers{_pid}
, rq(_rq)
, wq(_wq)
, pid(_pid)
{}
const Program& program;
Registers registers;
Queue& rq;
Queue& wq;
int pid;
int ip = 0;
int freq = 0;
bool step() {
if (ip >= program.size()) {
return false;
}
std::stringstream ss{program[ip]};
std::string c, p1, p2;
ss >> c >> p1 >> p2;
// std::cout << "\nip: " << ip << " : " << c << " : " << p1 << " : " << p2 << "\n";
if (c == "snd") {
wq.push_back(registers.regOrVal(p1)->second);
std::cout << "pid: " << pid << " - send " << wq.back() << "\n";
} else if (c == "set") {
auto r1 = registers.regOrVal(p1);
r1->second = registers.regOrVal(p2)->second;
} else if (c == "add") {
auto r1 = registers.regOrVal(p1);
r1->second += registers.regOrVal(p2)->second;
} else if (c == "mul") {
auto r1 = registers.regOrVal(p1);
r1->second *= registers.regOrVal(p2)->second;
} else if (c == "mod") {
auto r1 = registers.regOrVal(p1);
r1->second %= registers.regOrVal(p2)->second;
} else if (c == "rcv") {
if (rq.empty()) {
// block
std::cout << "pid: " << pid << " - recv blocked\n";
return true;
}
auto r1 = registers.regOrVal(p1);
r1->second = rq.front();
rq.pop_front();
std::cout << "pid: " << pid << " - recv " << r1->second << "\n";
} else if (c == "jgz") {
auto r1 = registers.regOrVal(p1);
if (r1->second > 0) {
ip += registers.regOrVal(p2)->second;
return true;
}
} else {
std::cerr << "ERROR: " << c << "\n";
}
++ip;
return true;
}
};
int main()
{
Program program;
std::string line;
while (std::getline(std::cin, line)) {
program.emplace_back(std::move(line));
}
Queue q0, q1;
Context c0(program, 0, q0, q1);
Context c1(program, 1, q1, q0);
for (;;) {
bool pid0 = c0.step();
bool pid1 = c1.step();
if (!pid0 && !pid1) {
break;
}
}
return 0;
}