aboutsummaryrefslogtreecommitdiff
path: root/2017/src/day21.cpp
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2025-11-07 12:04:46 +0100
committerThomas Schmucker <ts@its1.de>2025-11-07 12:04:46 +0100
commitbdd35a7bee7f23c912d0c453abc263805d8d8ccf (patch)
treedcd06076d36124ea8fdd16ea19db79717dde074c /2017/src/day21.cpp
parent756f22d58bb198b8f34589c112e1003614ccdcd6 (diff)
downloadadvent-of-code-bdd35a7bee7f23c912d0c453abc263805d8d8ccf.tar.gz
advent-of-code-bdd35a7bee7f23c912d0c453abc263805d8d8ccf.tar.bz2
advent-of-code-bdd35a7bee7f23c912d0c453abc263805d8d8ccf.zip
aoc 2017, days 21-25
Diffstat (limited to '2017/src/day21.cpp')
-rw-r--r--2017/src/day21.cpp186
1 files changed, 186 insertions, 0 deletions
diff --git a/2017/src/day21.cpp b/2017/src/day21.cpp
new file mode 100644
index 0000000..64af5b6
--- /dev/null
+++ b/2017/src/day21.cpp
@@ -0,0 +1,186 @@
1#include <algorithm>
2#include <filesystem>
3#include <fstream>
4#include <iostream>
5#include <map>
6#include <string>
7#include <vector>
8
9using namespace std;
10
11namespace {
12
13vector<string>
14split(const string& line, const string& delimiters)
15{
16 vector<string> result;
17
18 size_t start = 0;
19 size_t end = 0;
20
21 while ( (end = line.find_first_of(delimiters, start)) != string::npos ) {
22 if ( end != start ) {
23 result.emplace_back(line.substr(start, end - start));
24 }
25
26 start = end + 1;
27 }
28
29 if ( start != line.size() ) {
30 result.emplace_back(line.substr(start));
31 }
32
33 return result;
34}
35
36vector<string>
37rotate90(const vector<string>& input)
38{
39 if ( input.empty() ) {
40 return {};
41 }
42
43 const auto rows = input.size();
44 const auto cols = input[0].size();
45
46 vector<string> rotated(cols, string(rows, ' '));
47
48 for ( size_t row = 0; row != rows; ++row ) {
49 for ( size_t col = 0; col != cols; ++col ) {
50 rotated[col][rows - 1 - row] = input[row][col];
51 }
52 }
53
54 return rotated;
55}
56
57vector<string>
58flip(const vector<string>& input)
59{
60 vector<string> result = input;
61
62 // oder: ranges::reverse(result);
63 for ( auto& row: result ) {
64 ranges::reverse(row);
65 }
66
67 return result;
68}
69
70vector<vector<string>>
71generate_variants(vector<string> pattern)
72{
73 vector<vector<string>> variants;
74
75 for ( int flip_count = 0; flip_count < 2; ++flip_count ) {
76 for ( int round = 0; round < 4; ++round ) {
77 variants.push_back(pattern);
78 pattern = rotate90(pattern);
79 }
80 pattern = flip(pattern);
81 }
82
83 return variants;
84}
85
86map<vector<string>, vector<string>>
87read_file(const filesystem::path& filename)
88{
89 ifstream file{ filename };
90 map<vector<string>, vector<string>> data;
91
92 for ( string line; getline(file, line); ) {
93 auto parts = split(line, " ");
94 auto lhs = split(parts.at(0), "/");
95 auto rhs = split(parts.at(2), "/");
96
97 for ( const auto& variant: generate_variants(lhs) ) {
98 data[variant] = rhs;
99 }
100 }
101
102 return data;
103}
104
105vector<string>
106enhance(const vector<string>& image, const map<vector<string>, vector<string>>& rules)
107{
108 const auto size = image.size();
109 const auto block_size = (size % 2 == 0) ? 2U : 3U;
110 const auto new_block_size = block_size + 1;
111 const auto blocks_per_row = size / block_size;
112 const auto new_size = blocks_per_row * new_block_size;
113
114 vector<string> new_image(new_size, string(new_size, '.'));
115
116 // Für jeden Block...
117 for ( size_t block_row = 0; block_row != blocks_per_row; ++block_row ) {
118 for ( size_t block_col = 0; block_col != blocks_per_row; ++block_col ) {
119 // ...Extrahiere den Block als vector<string>
120 vector<string> block;
121 block.reserve(block_size);
122 for ( size_t row = 0; row != block_size; ++row ) {
123 block.push_back(image[(block_row * block_size) + row].substr(block_col * block_size, block_size));
124 }
125
126 const auto& new_block = rules.at(block);
127
128 // Füge neuen Block ins Bild ein
129 for ( size_t row = 0; row != new_block_size; ++row ) {
130 for ( size_t col = 0; col != new_block_size; ++col ) {
131 new_image[(block_row * new_block_size) + row][(block_col * new_block_size) + col] = new_block[row][col];
132 }
133 }
134 }
135 }
136
137 return new_image;
138}
139
140int
141count(const vector<string>& image)
142{
143 int count = 0;
144 for ( const auto& row: image ) {
145 for ( char chr: row ) {
146 if ( chr == '#' ) {
147 ++count;
148 }
149 }
150 }
151 return count;
152}
153
154int
155solve(const map<vector<string>, vector<string>>& rules, size_t iterations)
156{
157 vector<string> image = { ".#.", "..#", "###" };
158
159 while ( iterations-- > 0 ) {
160 image = enhance(image, rules);
161 }
162
163 return count(image);
164}
165
166void
167part1(const map<vector<string>, vector<string>>& rules)
168{
169 cout << "Part1: " << solve(rules, 5) << '\n';
170}
171
172void
173part2(const map<vector<string>, vector<string>>& rules)
174{
175 cout << "Part2: " << solve(rules, 18) << '\n';
176}
177
178} // namespace
179
180int
181main()
182{
183 auto rules = read_file("data/day21.txt");
184 part1(rules);
185 part2(rules);
186}