-
Notifications
You must be signed in to change notification settings - Fork 0
/
day13.h
109 lines (101 loc) · 2.7 KB
/
day13.h
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
#include <fstream>
#include <map>
#include <optional>
#include <set>
#include <unordered_map>
namespace {
using namespace std;
using IntcodeState = tuple<int, int, unordered_map<int, long long>>;
struct GameState {
set<pair<int, int>> blocks;
int paddle;
int ball;
int score;
};
unordered_map<int, long long> parse(ifstream input) {
unordered_map<int, long long> program;
long long value;
for (int pos = 0; input >> value; pos++) {
program[pos] = value;
input.ignore(1, ',');
}
return program;
}
optional<int> run(IntcodeState& state, optional<int> input) {
auto& [pos, base, program] = state;
for (int op; (op = program[pos] % 100) != 3 || input;) {
auto param = [&, mode = program[pos++] / 10]() mutable -> long long& {
mode /= 10;
switch (mode % 10) {
case 0:
return program[program[pos++]];
case 1:
return program[pos++];
case 2:
return program[base + program[pos++]];
}
};
if (op == 1) {
param() = param() + param();
} else if (op == 2) {
param() = param() * param();
} else if (op == 3) {
param() = *input;
input.reset();
} else if (op == 4) {
return param();
} else if (op == 5) {
pos = param() != 0 ? param() : pos + 1;
} else if (op == 6) {
pos = param() == 0 ? param() : pos + 1;
} else if (op == 7) {
auto left = param();
param() = left < param() ? 1 : 0;
} else if (op == 8) {
param() = param() == param() ? 1 : 0;
} else if (op == 9) {
base += param();
} else if (op == 99) {
return {};
}
}
return {};
}
void draw(GameState& gs, IntcodeState& is, optional<int> input) {
auto x = run(is, input);
do {
auto y = run(is, {});
auto tile = run(is, {});
if (x == -1 && y == 0)
gs.score = *tile;
else if (tile == 2)
gs.blocks.insert({ *x, *y });
else if (tile == 3)
gs.paddle = *x;
else if (tile == 4)
gs.ball = *x;
else if (tile == 0)
gs.blocks.erase({ *x, *y });
} while (x = run(is, {}));
}
int play(IntcodeState is) {
GameState gs;
draw(gs, is, {});
while (!gs.blocks.empty()) {
int joystick = gs.ball < gs.paddle ? -1 : gs.ball > gs.paddle ? 1 : 0;
draw(gs, is, joystick);
}
return gs.score;
}
auto part1(ifstream input) {
IntcodeState is{ 0, 0, parse(move(input)) };
GameState gs;
draw(gs, is, {});
return gs.blocks.size();
}
auto part2(ifstream input) {
auto program = parse(move(input));
program[0] = 2;
return play({ 0, 0, program });
}
}