aboutsummaryrefslogtreecommitdiff
path: root/2024/06/day06b.cpp
diff options
context:
space:
mode:
Diffstat (limited to '2024/06/day06b.cpp')
-rw-r--r--2024/06/day06b.cpp216
1 files changed, 216 insertions, 0 deletions
diff --git a/2024/06/day06b.cpp b/2024/06/day06b.cpp
new file mode 100644
index 0000000..2498536
--- /dev/null
+++ b/2024/06/day06b.cpp
@@ -0,0 +1,216 @@
1/*
2This is quite inefficient, but it still gives the right answer in less
3than a minute (25 seconds on my old laptop).
4*/
5
6#include <iostream>
7#include <algorithm>
8#include <string>
9#include <string_view>
10#include <vector>
11using namespace std;
12
13enum Direction { U = 0, D, R, L };
14Direction all_directions[] = {
15 Direction::U, Direction::D, Direction::R, Direction::L,
16};
17
18pair<int, int> step(pair<int, int> p, Direction d) {
19 auto [i, j] = p;
20
21 switch (d) {
22 case Direction::U:
23 return make_pair(i-1, j);
24 case Direction::D:
25 return make_pair(i+1, j);
26 case Direction::R:
27 return make_pair(i, j+1);
28 case Direction::L:
29 return make_pair(i, j-1);
30 }
31
32 return make_pair(-999,-999);
33}
34
35Direction turn(Direction d) {
36 switch (d) {
37 case Direction::U:
38 return Direction::R;
39 case Direction::D:
40 return Direction::L;
41 case Direction::R:
42 return Direction::D;
43 case Direction::L:
44 return Direction::U;
45 }
46
47 return Direction::U;
48}
49
50class Board {
51public:
52 const char out_of_bound = '$';
53 int M, N;
54
55 Board(vector<string> &lines) {
56 N = lines.size();
57 M = 0;
58 for (string l : lines)
59 M = max(M, (int)l.size());
60
61 cells = new char[M * N];
62 visited = new int[M * N];
63 for (int i = 0; i < N; i++) {
64 for (int j = 0; j < M; j++) {
65 cells[N*i + j] = j < (int)lines[i].size() ?
66 lines[i][j] : out_of_bound;
67 visited[N*i + j] = 0;
68 }
69 }
70 }
71
72 ~Board() {
73 delete []cells;
74 delete []visited;
75 }
76
77 char operator[](pair<int, int> p) {
78 int c = coord(p);
79 return c == -1 ? out_of_bound : cells[c];
80 }
81
82 bool is_visited(pair<int, int> p, Direction d) {
83 return get_vmask(p) & (1 << d);
84 }
85
86 void set_visited(pair<int, int> p, Direction d) {
87 toggle_vmask(p, d);
88 }
89
90 void clear_visited() {
91 for (int i = 0; i < N; i++)
92 for (int j = 0; j < M; j++)
93 set_vmask(make_pair(i, j), 0);
94 }
95
96 bool is_obstruction(pair<int, int> p) {
97 return (*this)[p] == '#';
98 }
99
100 void set_obstruction(pair<int, int> p) {
101 set_cell(p, '#');
102 }
103
104 void set_clean(pair<int, int> p) {
105 set_cell(p, '.');
106 }
107
108private:
109 char *cells;
110 int *visited;
111
112 int coord(pair<int, int> p) {
113 auto [i, j] = p;
114 return i >= N || i < 0 || j >= M || j < 0 ? -1 : N*i + j;
115 }
116
117 void set_cell(pair<int, int> p, char c) {
118 int i = coord(p);
119 cells[i] = c;
120 }
121
122 int get_vmask(pair<int, int> p) {
123 int i = coord(p);
124 return visited[i];
125 }
126
127 void set_vmask(pair<int, int> p, int x) {
128 int i = coord(p);
129 visited[i] = x;
130 }
131
132 void toggle_vmask(pair<int, int> p, Direction d) {
133 int i = coord(p);
134 visited[i] ^= 1 << d;
135 }
136};
137
138Direction guard_direction(char c) {
139 switch (c) {
140 case '^':
141 return Direction::U;
142 case 'v':
143 return Direction::D;
144 case '>':
145 return Direction::R;
146 case '<':
147 return Direction::L;
148 }
149
150 return Direction::U;
151}
152
153pair<pair<int, int>, Direction> find_guard(Board &board) {
154 pair<int, int> p(0, 0);
155 for (p.first = 0; p.first < board.N; p.first++) {
156 for (p.second = 0; p.second < board.M; p.second++) {
157 if (board[p] != '.' && board[p] != '#') {
158 Direction d = guard_direction(board[p]);
159 return make_pair(p, d);
160 }
161 }
162 }
163
164 return make_pair(make_pair(-999, -999), Direction::U);
165}
166
167bool isloop(pair<int, int> i, pair<int, int> p, Direction d, Board &board) {
168 bool ret = false;
169
170 board.set_obstruction(i);
171
172 while (true) {
173 auto q = step(p, d);
174 if (board.is_visited(p, d)) {
175 ret = true;
176 break;
177 }
178 board.set_visited(p, d);
179
180 if (board[q] == board.out_of_bound)
181 break;
182
183 if (board.is_obstruction(q)) {
184 d = turn(d);
185 } else {
186 p = q;
187 }
188 }
189
190 board.clear_visited();
191 board.set_clean(i);
192
193 return ret;
194}
195
196int main() {
197 string line;
198 vector<string> lines;
199 while (getline(cin, line))
200 lines.push_back(line);
201
202 Board board(lines);
203
204 int tot = 0;
205 auto [p, d] = find_guard(board);
206
207 pair i(0, 0);
208 for (i.first = 0; i.first < board.N; i.first++)
209 for (i.second = 0; i.second < board.M; i.second++)
210 if (board[i] == '.')
211 tot += isloop(i, p, d, board);
212
213 cout << tot << endl;
214
215 return 0;
216}

Generated with cgit - Back to sebastiano.tronto.net