diff options
| -rw-r--r-- | 2024/06/Makefile | 24 | ||||
| -rwxr-xr-x | 2024/06/b.out | bin | 0 -> 173576 bytes | |||
| -rw-r--r-- | 2024/06/day06a.cpp | 152 | ||||
| -rw-r--r-- | 2024/06/day06b.cpp | 216 |
4 files changed, 392 insertions, 0 deletions
diff --git a/2024/06/Makefile b/2024/06/Makefile new file mode 100644 index 0000000..8a6eea2 --- /dev/null +++ b/2024/06/Makefile | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | CC=g++ -std=c++20 -g -Wall | ||
| 2 | |||
| 3 | a: | ||
| 4 | ${CC} -o a.out day06a.cpp | ||
| 5 | |||
| 6 | b: | ||
| 7 | ${CC} -o b.out day06b.cpp | ||
| 8 | |||
| 9 | clean: | ||
| 10 | rm -f a b | ||
| 11 | |||
| 12 | atest: a | ||
| 13 | ./a.out | ||
| 14 | |||
| 15 | btest: b | ||
| 16 | ./b.out | ||
| 17 | |||
| 18 | arun: a | ||
| 19 | ./a.out < input | ||
| 20 | |||
| 21 | brun: b | ||
| 22 | ./b.out < input | ||
| 23 | |||
| 24 | .PHONY: a b clean atest btest arun brun | ||
diff --git a/2024/06/b.out b/2024/06/b.out new file mode 100755 index 0000000..1455953 --- /dev/null +++ b/2024/06/b.out | |||
| Binary files differ | |||
diff --git a/2024/06/day06a.cpp b/2024/06/day06a.cpp new file mode 100644 index 0000000..69b9340 --- /dev/null +++ b/2024/06/day06a.cpp | |||
| @@ -0,0 +1,152 @@ | |||
| 1 | #include <iostream> | ||
| 2 | #include <algorithm> | ||
| 3 | #include <string> | ||
| 4 | #include <string_view> | ||
| 5 | #include <vector> | ||
| 6 | using namespace std; | ||
| 7 | |||
| 8 | enum class Direction { U, D, R, L }; | ||
| 9 | Direction all_directions[] = { | ||
| 10 | Direction::U, Direction::D, Direction::R, Direction::L, | ||
| 11 | }; | ||
| 12 | |||
| 13 | pair<int, int> step(pair<int, int> p, Direction d) { | ||
| 14 | auto [i, j] = p; | ||
| 15 | |||
| 16 | switch (d) { | ||
| 17 | case Direction::U: | ||
| 18 | return make_pair(i-1, j); | ||
| 19 | case Direction::D: | ||
| 20 | return make_pair(i+1, j); | ||
| 21 | case Direction::R: | ||
| 22 | return make_pair(i, j+1); | ||
| 23 | case Direction::L: | ||
| 24 | return make_pair(i, j-1); | ||
| 25 | } | ||
| 26 | |||
| 27 | return make_pair(-999,-999); | ||
| 28 | } | ||
| 29 | |||
| 30 | Direction turn(Direction d) { | ||
| 31 | switch (d) { | ||
| 32 | case Direction::U: | ||
| 33 | return Direction::R; | ||
| 34 | case Direction::D: | ||
| 35 | return Direction::L; | ||
| 36 | case Direction::R: | ||
| 37 | return Direction::D; | ||
| 38 | case Direction::L: | ||
| 39 | return Direction::U; | ||
| 40 | } | ||
| 41 | |||
| 42 | return Direction::U; | ||
| 43 | } | ||
| 44 | |||
| 45 | class Board { | ||
| 46 | public: | ||
| 47 | const char out_of_bound = '$'; | ||
| 48 | int M, N; | ||
| 49 | |||
| 50 | Board(vector<string> &lines) { | ||
| 51 | N = lines.size(); | ||
| 52 | M = 0; | ||
| 53 | for (string l : lines) | ||
| 54 | M = max(M, (int)l.size()); | ||
| 55 | cells = new char[M * N]; | ||
| 56 | for (int i = 0; i < N; i++) | ||
| 57 | for (int j = 0; j < M; j++) | ||
| 58 | cells[N*i + j] = j < (int)lines[i].size() ? | ||
| 59 | lines[i][j] : out_of_bound; | ||
| 60 | } | ||
| 61 | |||
| 62 | ~Board() { | ||
| 63 | delete []cells; | ||
| 64 | } | ||
| 65 | |||
| 66 | char operator[](pair<int, int> p) { | ||
| 67 | int c = coord(p); | ||
| 68 | return c == -1 ? out_of_bound : cells[c]; | ||
| 69 | } | ||
| 70 | |||
| 71 | bool is_obstruction(pair<int, int> p) { | ||
| 72 | return (*this)[p] == '#'; | ||
| 73 | } | ||
| 74 | |||
| 75 | bool is_visited(pair<int, int> p) { | ||
| 76 | return (*this)[p] == 'x'; | ||
| 77 | } | ||
| 78 | |||
| 79 | void set_visited(pair<int, int> p) { | ||
| 80 | int c = coord(p); | ||
| 81 | cells[c] = 'x'; | ||
| 82 | } | ||
| 83 | |||
| 84 | private: | ||
| 85 | char *cells; | ||
| 86 | |||
| 87 | int coord(pair<int, int> p) { | ||
| 88 | auto [i, j] = p; | ||
| 89 | return i >= N || i < 0 || j >= M || j < 0 ? -1 : N*i + j; | ||
| 90 | } | ||
| 91 | }; | ||
| 92 | |||
| 93 | Direction guard_direction(char c) { | ||
| 94 | switch (c) { | ||
| 95 | case '^': | ||
| 96 | return Direction::U; | ||
| 97 | case 'v': | ||
| 98 | return Direction::D; | ||
| 99 | case '>': | ||
| 100 | return Direction::R; | ||
| 101 | case '<': | ||
| 102 | return Direction::L; | ||
| 103 | } | ||
| 104 | |||
| 105 | return Direction::U; | ||
| 106 | } | ||
| 107 | |||
| 108 | pair<pair<int, int>, Direction> find_guard(Board &board) { | ||
| 109 | pair<int, int> p(0, 0); | ||
| 110 | for (p.first = 0; p.first < board.N; p.first++) { | ||
| 111 | for (p.second = 0; p.second < board.M; p.second++) { | ||
| 112 | if (board[p] != '.' && board[p] != '#') { | ||
| 113 | Direction d = guard_direction(board[p]); | ||
| 114 | return make_pair(p, d); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | return make_pair(make_pair(-999, -999), Direction::U); | ||
| 120 | } | ||
| 121 | |||
| 122 | int main() { | ||
| 123 | string line; | ||
| 124 | vector<string> lines; | ||
| 125 | while (getline(cin, line)) | ||
| 126 | lines.push_back(line); | ||
| 127 | |||
| 128 | Board board(lines); | ||
| 129 | |||
| 130 | int tot = 1; | ||
| 131 | auto [p, d] = find_guard(board); | ||
| 132 | board.set_visited(p); | ||
| 133 | |||
| 134 | while (true) { | ||
| 135 | auto q = step(p, d); | ||
| 136 | if (board[q] == board.out_of_bound) | ||
| 137 | break; | ||
| 138 | if (board.is_obstruction(q)) { | ||
| 139 | d = turn(d); | ||
| 140 | } else { | ||
| 141 | p = q; | ||
| 142 | if (!board.is_visited(p)) { | ||
| 143 | board.set_visited(p); | ||
| 144 | tot++; | ||
| 145 | } | ||
| 146 | } | ||
| 147 | } | ||
| 148 | |||
| 149 | cout << tot << endl; | ||
| 150 | |||
| 151 | return 0; | ||
| 152 | } | ||
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 | /* | ||
| 2 | This is quite inefficient, but it still gives the right answer in less | ||
| 3 | than 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> | ||
| 11 | using namespace std; | ||
| 12 | |||
| 13 | enum Direction { U = 0, D, R, L }; | ||
| 14 | Direction all_directions[] = { | ||
| 15 | Direction::U, Direction::D, Direction::R, Direction::L, | ||
| 16 | }; | ||
| 17 | |||
| 18 | pair<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 | |||
| 35 | Direction 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 | |||
| 50 | class Board { | ||
| 51 | public: | ||
| 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 | |||
| 108 | private: | ||
| 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 | |||
| 138 | Direction 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 | |||
| 153 | pair<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 | |||
| 167 | bool 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 | |||
| 196 | int 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 | } | ||
