-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday15.h
118 lines (111 loc) · 3.22 KB
/
day15.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
110
111
112
113
114
115
116
117
118
#include <fstream>
#include <optional>
#include <queue>
#include <set>
#include <unordered_map>
namespace {
using namespace std;
using Location = pair<int, int>;
using State = tuple<int, int, unordered_map<int, long long>>;
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;
}
int run(State& state, optional<int> input) {
auto& [pos, base, program] = state;
while (program[pos] != 99) {
int op = program[pos] % 100;
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();
}
}
}
pair<int, pair<Location, State>> bfs(Location pos, State state) {
set<Location> visited;
queue<pair<int, pair<Location, State>>> unvisited;
unvisited.push({ 0, { pos, state } });
int steps;
pair<Location, State> ls;
while (!unvisited.empty()) {
tie(steps, ls) = move(unvisited.front());
auto [x, y] = ls.first;
auto adjacent = {
tuple{ 1, 2, pair{ x, y - 1 } },
tuple{ 2, 1, pair{ x, y + 1 } },
tuple{ 3, 4, pair{ x - 1, y } },
tuple{ 4, 3, pair{ x + 1, y } },
};
int viable = 0;
for (auto [forth, back, pos] : adjacent) {
if (visited.count(pos))
continue;
auto& state = ls.second;
auto status = run(state, forth);
if (status == 0) {
visited.insert(pos);
continue;
}
if (status == 1) {
run(state, back);
viable++;
}
if (status == 2)
return { steps + 1, { pos, state } };
}
for (auto [forth, back, pos] : adjacent) {
if (visited.count(pos))
continue;
[&](auto state) {
run(state, forth);
unvisited.push({ steps + 1, { pos, move(state) } });
}(!--viable ? move(ls.second) : ls.second);
}
visited.insert({ x, y });
unvisited.pop();
}
return { steps, {} };
}
int part1(ifstream input) {
auto program = parse(move(input));
return bfs({ 0, 0 }, { 0, 0, move(program) }).first;
}
int part2(ifstream input) {
auto program = parse(move(input));
auto [pos, state] = bfs({ 0, 0 }, { 0, 0, move(program) }).second;
return bfs(pos, move(state)).first;
}
}