aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--makefile3
-rw-r--r--src/day16.cpp139
2 files changed, 141 insertions, 1 deletions
diff --git a/makefile b/makefile
index 87d8aee..539cc3c 100644
--- a/makefile
+++ b/makefile
@@ -14,7 +14,8 @@ all: bin/day01 \
14 bin/day12 \ 14 bin/day12 \
15 bin/day13 \ 15 bin/day13 \
16 bin/day14 \ 16 bin/day14 \
17 bin/day15 17 bin/day15 \
18 bin/day16
18 19
19bin: 20bin:
20 mkdir $@ 21 mkdir $@
diff --git a/src/day16.cpp b/src/day16.cpp
new file mode 100644
index 0000000..68defad
--- /dev/null
+++ b/src/day16.cpp
@@ -0,0 +1,139 @@
1#include <array>
2#include <chrono>
3#include <fstream>
4#include <iostream>
5#include <map>
6#include <queue>
7#include <set>
8#include <string>
9#include <vector>
10using namespace std;
11
12vector<string>
13read_file(string_view filename)
14{
15 fstream input{ filename };
16 vector<string> data;
17
18 for ( string line; getline(input, line); ) {
19 data.emplace_back(line);
20 }
21
22 return data;
23}
24
25const unsigned DIR_UP = 0;
26const unsigned DIR_RIGHT = 1;
27const unsigned DIR_DOWN = 2;
28const unsigned DIR_LEFT = 3;
29
30size_t
31solve(const vector<string>& lines, tuple<size_t, size_t, unsigned int> start)
32{
33 static const array<tuple<size_t, size_t>, 4> movement{
34 make_tuple(0, -1),
35 make_tuple(1, 0),
36 make_tuple(0, 1),
37 make_tuple(-1, 0),
38 };
39
40 map<tuple<size_t, size_t, unsigned int>, bool> visited;
41
42 queue<tuple<size_t, size_t, unsigned int>> positions;
43
44 positions.emplace(start);
45
46 while ( !positions.empty() ) {
47 auto row = get<0>(positions.front());
48 auto col = get<1>(positions.front());
49 auto dir = get<2>(positions.front());
50 positions.pop();
51
52 while ( true ) {
53 col += get<0>(movement[dir]); // NOLINT
54 row += get<1>(movement[dir]); // NOLINT
55
56 if ( row >= lines.size() || col >= lines[0].size() ) {
57 break;
58 }
59
60 if ( visited[{ row, col, dir }] ) {
61 break;
62 }
63
64 visited[{ row, col, dir }] = true;
65
66 const auto chr = lines[row][col];
67
68 if ( chr == '|' && (dir == DIR_LEFT || dir == DIR_RIGHT) ) {
69 dir = (dir + 1) % 4;
70 positions.emplace(row, col, (dir + 2) % 4);
71 }
72 else if ( chr == '-' && (dir == DIR_UP || dir == DIR_DOWN) ) {
73 dir = (dir + 1) % 4;
74 positions.emplace(row, col, (dir + 2) % 4);
75 }
76 else if ( chr == '/' && (dir == DIR_LEFT || dir == DIR_RIGHT) ) {
77 dir = (dir + 3) % 4;
78 }
79 else if ( chr == '/' && (dir == DIR_UP || dir == DIR_DOWN) ) {
80 dir = (dir + 1) % 4;
81 }
82 else if ( chr == '\\' && (dir == DIR_LEFT || dir == DIR_RIGHT) ) {
83 dir = (dir + 1) % 4;
84 }
85 else if ( chr == '\\' && (dir == DIR_UP || dir == DIR_DOWN) ) {
86 dir = (dir + 3) % 4;
87 }
88 }
89 }
90
91 set<tuple<size_t, size_t>> foo;
92 for (const auto& bar: visited) {
93 foo.emplace(get<0>(bar.first), get<1>(bar.first));
94 }
95 return foo.size();
96}
97
98void
99part1(const vector<string>& lines)
100{
101 auto start = chrono::steady_clock::now();
102
103 auto sum = solve(lines, { 0, -1, DIR_RIGHT });
104
105 auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();
106
107 cout << sum << " (" << duration << "ms)" << endl;
108}
109
110void
111part2(const vector<string>& lines)
112{
113 const auto rows = lines.size();
114 const auto cols = lines[0].size();
115
116 auto start = chrono::steady_clock::now();
117
118 size_t sum = 0;
119 for ( size_t row = 0; row != rows; ++row ) {
120 sum = max(sum, solve(lines, { row, -1, DIR_RIGHT }));
121 sum = max(sum, solve(lines, { row, cols, DIR_LEFT }));
122 }
123 for ( size_t col = 0; col != cols; ++col ) {
124 sum = max(sum, solve(lines, { -1, col, DIR_DOWN }));
125 sum = max(sum, solve(lines, { rows, col, DIR_UP }));
126 }
127
128 auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();
129
130 cout << sum << " (" << duration << "ms)" << endl;
131}
132
133int
134main()
135{
136 const auto lines = read_file("data/day16.txt");
137 part1(lines);
138 part2(lines);
139}