aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/day14.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/day14.cpp b/src/day14.cpp
new file mode 100644
index 0000000..2b7a5b8
--- /dev/null
+++ b/src/day14.cpp
@@ -0,0 +1,243 @@
1#include <chrono>
2#include <cstddef>
3#include <fstream>
4#include <iostream>
5#include <map>
6#include <string>
7#include <vector>
8using namespace std;
9
10vector<string>
11read_file(string_view filename)
12{
13 fstream input{ filename };
14 vector<string> data;
15
16 for ( string line; getline(input, line); ) {
17 data.emplace_back(line);
18 }
19
20 return data;
21}
22
23void
24part1()
25{
26 const auto lines = read_file("data/day14.txt");
27
28 auto start = chrono::steady_clock::now();
29
30 size_t sum = 0;
31 for ( size_t col = 0; col != lines[0].size(); ++col ) {
32 size_t counter = lines.size();
33
34 for ( size_t row = 0; row != lines.size(); ++row ) {
35 if ( lines[row][col] == 'O' ) {
36 sum += counter;
37 --counter;
38 }
39 if ( lines[row][col] == '#' ) {
40 counter = lines.size() - row - 1;
41 }
42 }
43 }
44
45 auto duration = chrono::duration_cast<chrono::microseconds>(chrono::steady_clock::now() - start).count();
46
47 cout << sum << " (" << duration << " μs)" << endl;
48}
49
50void
51tilt_north(vector<string>& lines)
52{
53 for ( size_t col = 0; col != lines[0].size(); ++col ) {
54 size_t row = 0;
55 while ( row != lines.size() ) {
56 size_t stones = 0;
57 size_t empty = 0;
58
59 for ( size_t idx = row; idx != lines.size() && lines[idx][col] != '#'; ++idx ) {
60 if ( lines[idx][col] == '.' ) {
61 ++empty;
62 }
63 if ( lines[idx][col] == 'O' ) {
64 ++stones;
65 }
66 }
67
68 while ( stones-- != 0 ) {
69 lines[row++][col] = 'O';
70 }
71
72 while ( empty-- != 0 ) {
73 lines[row++][col] = '.';
74 }
75
76 while ( row != lines.size() && lines[row][col] == '#' ) {
77 ++row;
78 }
79 }
80 }
81}
82
83void
84tilt_south(vector<string>& lines)
85{
86 for ( size_t col = 0; col != lines[0].size(); ++col ) {
87 size_t row = 0;
88 while ( row != lines.size() ) {
89 size_t stones = 0;
90 size_t empty = 0;
91
92 for ( size_t idx = row; idx != lines.size() && lines[idx][col] != '#'; ++idx ) {
93 if ( lines[idx][col] == '.' ) {
94 ++empty;
95 }
96 if ( lines[idx][col] == 'O' ) {
97 ++stones;
98 }
99 }
100
101 while ( empty-- != 0 ) {
102 lines[row++][col] = '.';
103 }
104
105 while ( stones-- != 0 ) {
106 lines[row++][col] = 'O';
107 }
108
109 while ( row != lines.size() && lines[row][col] == '#' ) {
110 ++row;
111 }
112 }
113 }
114}
115
116void
117tilt_west(vector<string>& lines)
118{
119 for ( size_t row = 0; row != lines.size(); ++row ) {
120 size_t col = 0;
121 while ( col != lines[0].size() ) {
122 size_t stones = 0;
123 size_t empty = 0;
124
125 for ( size_t idx = col; idx != lines[0].size() && lines[row][idx] != '#'; ++idx ) {
126 if ( lines[row][idx] == '.' ) {
127 ++empty;
128 }
129 if ( lines[row][idx] == 'O' ) {
130 ++stones;
131 }
132 }
133
134 while ( stones-- != 0 ) {
135 lines[row][col++] = 'O';
136 }
137
138 while ( empty-- != 0 ) {
139 lines[row][col++] = '.';
140 }
141
142 while ( col != lines[0].size() && lines[row][col] == '#' ) {
143 ++col;
144 }
145 }
146 }
147}
148
149void
150tilt_east(vector<string>& lines)
151{
152 for ( size_t row = 0; row != lines.size(); ++row ) {
153 size_t col = 0;
154 while ( col != lines[0].size() ) {
155 size_t stones = 0;
156 size_t empty = 0;
157
158 for ( size_t idx = col; idx != lines[0].size() && lines[row][idx] != '#'; ++idx ) {
159 if ( lines[row][idx] == '.' ) {
160 ++empty;
161 }
162 if ( lines[row][idx] == 'O' ) {
163 ++stones;
164 }
165 }
166
167 while ( empty-- != 0 ) {
168 lines[row][col++] = '.';
169 }
170
171 while ( stones-- != 0 ) {
172 lines[row][col++] = 'O';
173 }
174
175 while ( col != lines[0].size() && lines[row][col] == '#' ) {
176 ++col;
177 }
178 }
179 }
180}
181
182void
183tilt(vector<string>& lines)
184{
185 tilt_north(lines);
186 tilt_west(lines);
187 tilt_south(lines);
188 tilt_east(lines);
189}
190
191size_t
192calc(const vector<string>& lines)
193{
194 size_t sum = 0;
195 size_t counter = lines.size();
196 for ( const auto& line: lines ) {
197 sum += counter * static_cast<size_t>(count_if(line.begin(), line.end(), [](char chr) { return chr == 'O'; }));
198 --counter;
199 }
200 return sum;
201}
202
203void
204part2()
205{
206 auto lines = read_file("data/day14.txt");
207
208 auto start = chrono::steady_clock::now();
209 map<vector<string>, long> cache;
210
211 const long dest = 1'000'000'000;
212
213 for ( long index = 0; true; ++index ) {
214 auto iter = cache.find(lines);
215 if ( iter != cache.end() ) {
216 auto offset = iter->second;
217 auto cycle_length = index - offset;
218
219 auto moves_required = (dest - offset) % cycle_length;
220
221 while ( moves_required-- != 0 ) {
222 tilt(lines);
223 }
224
225 auto duration = chrono::duration_cast<chrono::milliseconds>(chrono::steady_clock::now() - start).count();
226
227 cout << calc(lines) << " (" << duration << " ms)" << endl;
228 break;
229 }
230 else {
231 cache[lines] = index;
232 }
233
234 tilt(lines);
235 }
236}
237
238int
239main()
240{
241 part1();
242 part2();
243}