Skip to content

Commit 4b871d7

Browse files
committed
Add 2017 day 18 cpp
1 parent f7efabe commit 4b871d7

File tree

4 files changed

+369
-1
lines changed

4 files changed

+369
-1
lines changed

2017/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ This folder contains solutions to each of the problems in Advent of Code 2017 in
2525
| <nobr> [Day 15: Dueling Generators](https://adventofcode.com/2017/day/15) </nobr> | <nobr> [Part 1](/2017/cpp/day_15a.cpp) [Part 2](/2017/cpp/day_15b.cpp) </nobr> |[Link](/2017/input/day_15_input)|[Link](/2017/sample_input/day_15_sample_input)|[Link](/2017/puzzles/day_15_puzzle)|
2626
| <nobr> [Day 16: Permutation Promenade](https://adventofcode.com/2017/day/16) </nobr> | <nobr> [Part 1](/2017/cpp/day_16a.cpp) [Part 2](/2017/cpp/day_16b.cpp) </nobr> |[Link](/2017/input/day_16_input)|[Link](/2017/sample_input/day_16_sample_input)|[Link](/2017/puzzles/day_16_puzzle)|
2727
| <nobr> [Day 17: Spinlock](https://adventofcode.com/2017/day/17) </nobr> | <nobr> [Part 1](/2017/cpp/day_17a.cpp) [Part 2](/2017/cpp/day_17b.cpp) </nobr> |[Link](/2017/input/day_17_input)|[Link](/2017/sample_input/day_17_sample_input)|[Link](/2017/puzzles/day_17_puzzle)|
28+
| <nobr> [Day 18: Duet](https://adventofcode.com/2017/day/18) </nobr> | <nobr> [Part 1](/2017/cpp/day_18a.cpp) [Part 2](/2017/cpp/day_18b.cpp) </nobr> |[Link](/2017/input/day_18_input)|[Link](/2017/sample_input/day_18_sample_input)|[Link](/2017/puzzles/day_18_puzzle)|
2829

2930
#### TODO ####
3031

3132
|Puzzle|C++ Solutions|Input|Sample Input|Puzzle page with solutions|
3233
|:---:|:---:|:---:|:---:|:---:|
33-
| <nobr> [Day 18: ](https://adventofcode.com/2017/day/18) </nobr> | <nobr> [Part 1](/2017/cpp/day_18a.cpp) [Part 2](/2017/cpp/day_18b.cpp) </nobr> |[Link](/2017/input/day_18_input)|[Link](/2017/sample_input/day_18_sample_input)|[Link](/2017/puzzles/day_18_puzzle)|
3434
| <nobr> [Day 19: ](https://adventofcode.com/2017/day/19) </nobr> | <nobr> [Part 1](/2017/cpp/day_19a.cpp) [Part 2](/2017/cpp/day_19b.cpp) </nobr> |[Link](/2017/input/day_19_input)|[Link](/2017/sample_input/day_19_sample_input)|[Link](/2017/puzzles/day_19_puzzle)|
3535
| <nobr> [Day 20: ](https://adventofcode.com/2017/day/20) </nobr> | <nobr> [Part 1](/2017/cpp/day_20a.cpp) [Part 2](/2017/cpp/day_20b.cpp) </nobr> |[Link](/2017/input/day_20_input)|[Link](/2017/sample_input/day_20_sample_input)|[Link](/2017/puzzles/day_20_puzzle)|
3636
| <nobr> [Day 21: ](https://adventofcode.com/2017/day/21) </nobr> | <nobr> [Part 1](/2017/cpp/day_21a.cpp) [Part 2](/2017/cpp/day_21b.cpp) </nobr> |[Link](/2017/input/day_21_input)|[Link](/2017/sample_input/day_21_sample_input)|[Link](/2017/puzzles/day_21_puzzle)|

2017/cpp/day_18a.cpp

+145
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
#include <fstream>
2+
#include <iostream>
3+
#include <string>
4+
#include <unordered_map>
5+
#include <vector>
6+
#include <variant>
7+
#include <queue>
8+
9+
// HINT: When the puzzle says X or Y, unless it specifies register, X or Y can be a number
10+
// jgz 1 3 is a possibility
11+
// add p b is a possibility
12+
13+
enum class InstructionType{
14+
UNKNOWN, SND, SET, ADD, MUL, MOD, RCV, JGZ
15+
};
16+
17+
struct Instruction {
18+
std::string line;
19+
InstructionType type;
20+
std::array<std::variant<long long, char>,2> args;
21+
22+
long long reg() const {
23+
return std::get<char>(args[0]);
24+
}
25+
26+
long long get_value (const int idx, std::unordered_map<char, long long>& regs) const {
27+
return args[idx].index() == 0 ? std::get<long long>(args[idx]) : regs[std::get<char>(args[idx])];
28+
}
29+
};
30+
31+
InstructionType parse_type(const std::string& instr) {
32+
if (instr == "snd") {
33+
return InstructionType::SND;
34+
} else if (instr == "set") {
35+
return InstructionType::SET;
36+
} else if (instr == "add") {
37+
return InstructionType::ADD;
38+
} else if (instr == "mul") {
39+
return InstructionType::MUL;
40+
} else if (instr == "mod") {
41+
return InstructionType::MOD;
42+
} else if (instr == "rcv") {
43+
return InstructionType::RCV;
44+
} else if (instr == "jgz") {
45+
return InstructionType::JGZ;
46+
}
47+
std::cout << "UNKNOWN" << '\n';
48+
exit(0);
49+
return InstructionType::UNKNOWN;
50+
}
51+
52+
53+
std::vector<Instruction> parse_instructions (std::ifstream& file) {
54+
std::vector<Instruction> instructions;
55+
std::string line;
56+
while(std::getline(file, line)) {
57+
// std::cout << line << '\n';
58+
Instruction i;
59+
i.line = line;
60+
i.type = parse_type(line.substr(0, 3));
61+
int next = 0;
62+
if (line[4] >= 'a' && line[4] <='z') {
63+
// std::cout << "Args 1 is a register: " << char(line[4]) <<'\n';
64+
i.args[0] = char(line[4]);
65+
next = 6;
66+
} else {
67+
next = line.find(' ', 4);
68+
if (next == std::string::npos) {
69+
// std::cout << "npos" << '\n';
70+
next == line.size();
71+
}
72+
// std::cout << "Args 1 is a number: " << std::stoi(line.substr(4, next - 4)) << '\n';
73+
i.args[0] = std::stoi(line.substr(4, next - 4));
74+
if (next != std::string::npos) {
75+
next++;
76+
}
77+
}
78+
// std::cout << line.size() << ' ' << next << '\n';
79+
if (line.size() >= next) {
80+
// std::cout << "Second args exists; size == " << line.size() << " > " << next << '\n';
81+
if (line[next] >= 'a' && line[next] <='z') {
82+
i.args[1] = char(line[next]);
83+
// std::cout << "Args 2 is a register: " << char(line[next]) <<'\n';
84+
} else {
85+
// std::cout << "Args 2 is a number: " << std::stoi(line.substr(next, line.size() - next)) << '\n';
86+
i.args[1] = std::stoi(line.substr(next, line.size() - next));
87+
}
88+
}
89+
90+
instructions.push_back(i);
91+
}
92+
// exit(0);
93+
return instructions;
94+
}
95+
96+
97+
int main(int argc, char* argv[]) {
98+
const std::string input = (argc > 1) ? argv[1] : "../input/day_18_input" ;
99+
std::ifstream file(input);
100+
std::string line;
101+
std::unordered_map<char, long long> regs;
102+
const std::vector<Instruction> instructions = parse_instructions(file);
103+
std::size_t instruction_ptr = 0;
104+
long long last_played = -1;
105+
while (instruction_ptr < instructions.size()) {
106+
const auto& instruction = instructions[instruction_ptr];
107+
// std::cout << instruction_ptr << ": " << instruction.line << '\n';
108+
if (instruction.type == InstructionType::SND) {
109+
if (regs[instruction.reg()] >= 0) {
110+
last_played = regs[instruction.reg()];
111+
}
112+
instruction_ptr++;
113+
} else if (instruction.type == InstructionType::SET) {
114+
regs[instruction.reg()] = instruction.get_value(1, regs);
115+
instruction_ptr++;
116+
} else if (instruction.type == InstructionType::ADD) {
117+
regs[instruction.reg()] += instruction.get_value(1, regs);
118+
instruction_ptr++;
119+
} else if (instruction.type == InstructionType::MUL) {
120+
regs[instruction.reg()] *= instruction.get_value(1, regs);
121+
instruction_ptr++;
122+
} else if (instruction.type == InstructionType::MOD) {
123+
regs[instruction.reg()] = regs[instruction.reg()] % instruction.get_value(1, regs);
124+
instruction_ptr++;
125+
} else if (instruction.type == InstructionType::RCV) {
126+
if(regs[instruction.reg()] != 0) {
127+
std::cout << last_played << '\n';
128+
return 0;
129+
}
130+
instruction_ptr++;
131+
} else if (instruction.type == InstructionType::JGZ) {
132+
// std::cout << instruction.get_value(0, regs) << '\n';
133+
if(instruction.get_value(0, regs) > 0) {
134+
instruction_ptr += instruction.get_value(1, regs);
135+
} else {
136+
instruction_ptr++;
137+
}
138+
} else {
139+
std::cout << "UNKNOWN" << '\n';
140+
exit(0);
141+
}
142+
}
143+
144+
return 0;
145+
}

2017/cpp/day_18b.cpp

+205
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
#include <fstream>
2+
#include <iostream>
3+
#include <string>
4+
#include <unordered_map>
5+
#include <vector>
6+
#include <variant>
7+
#include <queue>
8+
9+
// HINT: When the puzzle says X or Y, unless it specifies register, X or Y can be a number
10+
// jgz 1 3 is a possibility
11+
// add p b is a possibility
12+
13+
enum class InstructionType{
14+
UNKNOWN, SND, SET, ADD, MUL, MOD, RCV, JGZ
15+
};
16+
17+
struct Instruction {
18+
std::string line;
19+
InstructionType type;
20+
std::array<std::variant<long long, char>,2> args;
21+
22+
long long reg() const {
23+
return std::get<char>(args[0]);
24+
}
25+
26+
long long get_value (const int idx, std::unordered_map<char, long long>& regs) const {
27+
return args[idx].index() == 0 ? std::get<long long>(args[idx]) : regs[std::get<char>(args[idx])];
28+
}
29+
};
30+
31+
InstructionType parse_type(const std::string& instr) {
32+
if (instr == "snd") {
33+
return InstructionType::SND;
34+
} else if (instr == "set") {
35+
return InstructionType::SET;
36+
} else if (instr == "add") {
37+
return InstructionType::ADD;
38+
} else if (instr == "mul") {
39+
return InstructionType::MUL;
40+
} else if (instr == "mod") {
41+
return InstructionType::MOD;
42+
} else if (instr == "rcv") {
43+
return InstructionType::RCV;
44+
} else if (instr == "jgz") {
45+
return InstructionType::JGZ;
46+
}
47+
std::cout << "UNKNOWN" << '\n';
48+
exit(0);
49+
return InstructionType::UNKNOWN;
50+
}
51+
52+
struct Program {
53+
Program(const int id) : id(id) {
54+
for (char ch = 'a'; ch <= 'z'; ch++) {
55+
regs[ch] = 0;
56+
// std::cout << ch << ' ' << regs[ch] << '\n';
57+
}
58+
regs['p'] = id;
59+
// std::cout << 'p' << ' ' << regs['p'] << '\n' << '\n';
60+
}
61+
int id;
62+
std::queue<int> q;
63+
std::size_t instruction_ptr = 0;
64+
std::unordered_map<char, long long> regs;
65+
bool stuck = false;
66+
bool complete = false;
67+
68+
std::pair<bool, long long> execute(const std::vector<Instruction>& instructions) {
69+
if (complete) {
70+
return {false,0};
71+
}
72+
if (instruction_ptr >= instructions.size()) {
73+
complete = true;
74+
std::cout << "Complete" << '\n';
75+
return {false,0};
76+
}
77+
const auto& instruction = instructions[instruction_ptr];
78+
// std::cout << id<< ": " << instruction_ptr << " -> " << instruction.line << '\n';
79+
if (instruction.type == InstructionType::SND) {
80+
instruction_ptr++;
81+
// if (regs[instruction.reg()] >= 0) {
82+
return {true, instruction.get_value(0, regs)};
83+
// }
84+
} else if (instruction.type == InstructionType::SET) {
85+
regs[instruction.reg()] = instruction.get_value(1, regs);
86+
instruction_ptr++;
87+
} else if (instruction.type == InstructionType::ADD) {
88+
regs[instruction.reg()] += instruction.get_value(1, regs);
89+
instruction_ptr++;
90+
} else if (instruction.type == InstructionType::MUL) {
91+
regs[instruction.reg()] *= instruction.get_value(1, regs);
92+
instruction_ptr++;
93+
} else if (instruction.type == InstructionType::MOD) {
94+
regs[instruction.reg()] = regs[instruction.reg()] % instruction.get_value(1, regs);
95+
instruction_ptr++;
96+
} else if (instruction.type == InstructionType::RCV) {
97+
if(!q.empty()) {
98+
regs[instruction.reg()] = q.front();
99+
q.pop();
100+
stuck = false;
101+
// std::cout << id <<": Un Stuck " << '\n';
102+
instruction_ptr++;
103+
} else {
104+
// std::cout << id <<": Stuck " << '\n';
105+
stuck = true;
106+
}
107+
} else if (instruction.type == InstructionType::JGZ) {
108+
// std::cout << instruction.get_value(0, regs) << '\n';
109+
if(instruction.get_value(0, regs) > 0) {
110+
// std::cout << instruction.get_value(1, regs) << '\n';
111+
// std::cout << "Jump: " << instruction_ptr << ": " << instructions[instruction_ptr].line << " ---> ";
112+
instruction_ptr += instruction.get_value(1, regs);
113+
// std::cout << instruction_ptr << ": " << instructions[instruction_ptr].line << '\n';
114+
} else {
115+
instruction_ptr++;
116+
}
117+
} else {
118+
std::cout << "UNKNOWN" << '\n';
119+
exit(0);
120+
}
121+
// std::cout << id << ": ";
122+
// for (char ch = 'a'; ch <= 'z'; ch++) {
123+
// if (regs[ch] != 0) {
124+
// std::cout << '(' << ch << "," << regs[ch] << ')' << ' ';
125+
// }
126+
// }
127+
// std::cout << '\n';
128+
return {false, 0};
129+
}
130+
};
131+
132+
std::vector<Instruction> parse_instructions (std::ifstream& file) {
133+
std::vector<Instruction> instructions;
134+
std::string line;
135+
while(std::getline(file, line)) {
136+
// std::cout << line << '\n';
137+
Instruction i;
138+
i.line = line;
139+
i.type = parse_type(line.substr(0, 3));
140+
int next = 0;
141+
if (line[4] >= 'a' && line[4] <='z') {
142+
// std::cout << "Args 1 is a register: " << char(line[4]) <<'\n';
143+
i.args[0] = char(line[4]);
144+
next = 6;
145+
} else {
146+
next = line.find(' ', 4);
147+
if (next == std::string::npos) {
148+
// std::cout << "npos" << '\n';
149+
next == line.size();
150+
}
151+
// std::cout << "Args 1 is a number: " << std::stoi(line.substr(4, next - 4)) << '\n';
152+
i.args[0] = std::stoi(line.substr(4, next - 4));
153+
if (next != std::string::npos) {
154+
next++;
155+
}
156+
}
157+
// std::cout << line.size() << ' ' << next << '\n';
158+
if (line.size() >= next) {
159+
// std::cout << "Second args exists; size == " << line.size() << " > " << next << '\n';
160+
if (line[next] >= 'a' && line[next] <='z') {
161+
i.args[1] = char(line[next]);
162+
// std::cout << "Args 2 is a register: " << char(line[next]) <<'\n';
163+
} else {
164+
// std::cout << "Args 2 is a number: " << std::stoi(line.substr(next, line.size() - next)) << '\n';
165+
i.args[1] = std::stoi(line.substr(next, line.size() - next));
166+
}
167+
}
168+
169+
instructions.push_back(i);
170+
}
171+
// exit(0);
172+
return instructions;
173+
}
174+
175+
int main(int argc, char* argv[]) {
176+
const std::string input = (argc > 1) ? argv[1] : "../input/day_18_input" ;
177+
std::ifstream file(input);
178+
std::vector<Program> programs = {Program(0), Program(1)};
179+
const std::vector<Instruction> instructions = parse_instructions(file);
180+
std::size_t ans = 0;
181+
while (!(programs[0].stuck || programs[0].complete) || !(programs[1].stuck || programs[1].complete)) {
182+
// std::cout << programs[0].stuck << programs[1].stuck << programs[0].complete << programs[1].complete << '\n';
183+
// if ((programs[0].stuck && programs[1].stuck)) {
184+
// std::cout << "both stuck" << '\n';
185+
// }
186+
// if (programs[0].complete && programs[1].complete) {
187+
// std::cout << "both complete" << '\n';
188+
// }
189+
std::pair<bool, long long> result_0 = programs[0].execute(instructions);
190+
std::pair<bool, long long> result_1 = programs[1].execute(instructions);
191+
if (result_0.first) {
192+
programs[1].q.push(result_0.second);
193+
programs[1].stuck = false;
194+
}
195+
if (result_1.first) {
196+
ans++;
197+
programs[0].q.push(result_1.second);
198+
programs[0].stuck = false;
199+
}
200+
}
201+
// std::cout << programs[0].stuck << programs[1].stuck << programs[0].complete << programs[1].complete << '\n';
202+
203+
std::cout << ans << '\n';
204+
return 0;
205+
}

2017/sample_input/day_18_sample_input

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
set a 1
2+
add a 2
3+
mul a a
4+
mod a 5
5+
snd a
6+
set a 0
7+
rcv a
8+
jgz a -1
9+
set a 1
10+
jgz a -2
11+
12+
snd 1
13+
snd 2
14+
snd p
15+
rcv a
16+
rcv b
17+
rcv c
18+
rcv d

0 commit comments

Comments
 (0)