aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2024/src/day20.cpp108
1 files changed, 108 insertions, 0 deletions
diff --git a/2024/src/day20.cpp b/2024/src/day20.cpp
new file mode 100644
index 0000000..42a2fba
--- /dev/null
+++ b/2024/src/day20.cpp
@@ -0,0 +1,108 @@
1#include <fstream>
2#include <iostream>
3#include <map>
4#include <queue>
5#include <set>
6#include <string>
7#include <tuple>
8#include <vector>
9using namespace std;
10
11using pos_type = tuple<size_t, size_t>;
12
13tuple<pos_type, pos_type, set<pos_type>>
14read_file(string_view filename)
15{
16 fstream input{ filename };
17 set<pos_type> walls;
18 pos_type start;
19 pos_type end;
20
21 size_t yPos = 0;
22 for ( string line; getline(input, line); ) {
23 for ( size_t xPos = 0; xPos != line.size(); ++xPos ) {
24 auto chr = line[xPos];
25 if ( chr == '#' ) {
26 walls.emplace(xPos, yPos);
27 }
28 else if ( chr == 'S' ) {
29 start = { xPos, yPos };
30 }
31 else if ( chr == 'E' ) {
32 end = { xPos, yPos };
33 }
34 }
35 ++yPos;
36 }
37
38 return { start, end, walls };
39}
40
41map<pos_type, long>
42bfs(const tuple<pos_type, pos_type, set<pos_type>>& data)
43{
44 const auto& [start, end, walls] = data;
45
46 map<pos_type, long> path;
47
48 set<pos_type> seen;
49
50 queue<tuple<pos_type, long>> queue;
51 queue.push({ start, 0 });
52
53 while ( !queue.empty() ) {
54 auto [pos, dist] = queue.front();
55 queue.pop();
56
57 if ( seen.contains(pos) ) {
58 continue;
59 }
60 seen.insert(pos);
61
62 path[pos] = dist;
63
64 if ( pos == end ) {
65 break;
66 }
67
68 auto [x, y] = pos;
69 for ( const auto& new_pos: vector<pos_type>{ { x - 1, y }, { x, y - 1 }, { x + 1, y }, { x, y + 1 } } ) {
70 if ( walls.contains(new_pos) ) {
71 continue;
72 }
73 queue.push({ new_pos, dist + 1 });
74 }
75 }
76 return path;
77}
78
79void
80part1(const tuple<pos_type, pos_type, set<pos_type>>& data)
81{
82 auto path = bfs(data);
83
84 const auto& [start, end, walls] = data;
85
86 long count = 0;
87 for ( const auto& [pos, dist]: path ) {
88 auto [x, y] = pos;
89
90 for ( const auto& [dx, dy]: vector<pos_type>{ { -1, 0 }, { 0, -1 }, { 1, 0 }, { 0, 1 } } ) {
91 if ( !walls.contains({ x + dx, y + dy }) ) {
92 continue;
93 }
94 pos_type new_pos{ x + 2 * dx, y + 2 * dy };
95 if ( path.contains(new_pos) && dist < path.at(new_pos) && path.at(new_pos) - dist >= 100 + 2 ) {
96 ++count;
97 }
98 }
99 }
100 cout << count << endl;
101}
102
103int
104main()
105{
106 auto data = read_file("data/day20.txt");
107 part1(data);
108}