-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy path22.cpp
117 lines (97 loc) · 2.98 KB
/
22.cpp
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
#include <chrono>
#include <iostream>
#include <unordered_map>
using std::unordered_map;
struct Point {
int row;
int col;
bool operator==(const Point &o) const noexcept {
return row == o.row && col == o.col;
}
void operator+=(const Point &o) {
row += o.row;
col += o.col;
}
};
constexpr char CLEAN = 0;
constexpr char WEAKENED = 1;
constexpr char INFECTED = 2;
constexpr char FLAGGED = 3;
namespace std {
template <> struct hash<Point> {
inline size_t operator()(const Point &p) const noexcept {
return static_cast<size_t>((p.row << 16) ^ p.col);
}
};
} // namespace std
unordered_map<Point, unsigned char> parse_input() {
std::string line;
unordered_map<Point, unsigned char> grid;
Point pos = {0, 0};
while (std::getline(std::cin, line)) {
// if start position is at our initialization value
if (pos == Point{0, 0}) {
// update start pos to be relative to middle
// so 0,0 is {12,12} in our input
pos.row = -static_cast<int>(line.size() / 2);
pos.col = pos.row;
}
for (const char ch : line) {
grid[pos] = ch == '#' ? INFECTED : CLEAN;
++pos.col;
}
++pos.row;
pos.col = -static_cast<int>(line.size() / 2);
}
return grid;
}
int solve_pt1(unordered_map<Point, unsigned char> grid) {
int infection_count = 0;
Point pos = {0, 0};
Point directions[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
unsigned int dir = 0; // start facing north
for (int i = 0; i < 10000; ++i) {
dir = (grid[pos] ? dir + 1 : dir - 1) % 4;
grid[pos] = grid[pos] == INFECTED ? CLEAN : INFECTED;
if (grid[pos] == INFECTED) {
infection_count++;
}
pos += directions[dir];
}
return infection_count;
}
int solve_pt2(unordered_map<Point, unsigned char> grid) {
int infection_count = 0;
Point pos = {0, 0};
Point directions[] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}};
// lookup tables so we can be branchless inside the loop
unsigned char next_state[] = {WEAKENED, INFECTED, FLAGGED, CLEAN};
int state_values[] = {0, 0, 1, 0};
int dd[] = {-1, 0, 1, 2};
unsigned char s;
unsigned int dir = 0; // start facing north
for (int i = 0; i < 10000000; ++i) {
s = grid[pos];
grid[pos] = next_state[s];
infection_count += state_values[next_state[s]];
dir = static_cast<unsigned int>((static_cast<int>(dir) + dd[s])) % 4;
pos += directions[dir];
}
return infection_count;
}
int main() {
auto tstart = std::chrono::high_resolution_clock::now();
unordered_map<Point, unsigned char> grid = parse_input();
int pt1 = solve_pt1(grid);
int pt2 = solve_pt2(grid);
std::cout << "--- Day 22: Sporifica Virus ---\n";
std::cout << "Part 1: " << pt1 << "\n";
std::cout << "Part 2: " << pt2 << "\n";
auto tstop = std::chrono::high_resolution_clock::now();
auto duration =
std::chrono::duration_cast<std::chrono::microseconds>(tstop - tstart);
std::cout << "Time: " << (static_cast<double>(duration.count()) / 1000.0)
<< " ms"
<< "\n";
return EXIT_SUCCESS;
}