1
+ #include < algorithm>
2
+ #include < fstream>
3
+ #include < iostream>
4
+ #include < string>
5
+ #include < limits>
6
+ #include < unordered_map>
7
+ #include < unordered_set>
8
+ #include < vector>
9
+ #include < regex>
10
+ #include < cassert>
11
+ #include < cmath>
12
+
13
+ struct Coord2D {
14
+ int row;
15
+ int col;
16
+
17
+ Coord2D (const int row = 0 , const int col = 0 ) : row(row) , col(col) {}
18
+
19
+ Coord2D operator + (const Coord2D& c) const {
20
+ Coord2D ans;
21
+ ans.row = row + c.row ;
22
+ ans.col = col + c.col ;
23
+ return ans;
24
+ }
25
+
26
+ bool operator == (const Coord2D& c) const {
27
+ return row == c.row && col == c.col ;
28
+ }
29
+
30
+
31
+
32
+ Coord2D operator - (const Coord2D& c) const {
33
+ Coord2D ans;
34
+ ans.row = row - c.row ;
35
+ ans.col = col - c.col ;
36
+ return ans;
37
+ }
38
+
39
+ Coord2D operator += (const Coord2D& c) {
40
+ row += c.row ;
41
+ col += c.col ;
42
+ return *this ;
43
+ }
44
+ };
45
+
46
+ struct hasher {
47
+ std::size_t operator ()(const Coord2D& c) const {
48
+ return 1000000 * c.row + c.col ;
49
+ }
50
+ };
51
+
52
+ void print_pattern (const std::unordered_map<Coord2D, char , hasher>& pattern) {
53
+ const int dim = std::sqrt (pattern.size ());
54
+ for (int row = 0 ; row < dim; row++) {
55
+ for (int col = 0 ; col < dim; col++) {
56
+ std::cout << pattern.at (Coord2D (row,col));
57
+ }
58
+ std::cout << ' \n ' ;
59
+ }
60
+ std::cout << ' \n ' ;
61
+ }
62
+
63
+ int count_on_in_pattern (const std::unordered_map<Coord2D, char , hasher>& pattern) {
64
+ const int dim = std::sqrt (pattern.size ());
65
+ int count = 0 ;
66
+ for (int row = 0 ; row < dim; row++) {
67
+ for (int col = 0 ; col < dim; col++) {
68
+ if (pattern.at (Coord2D (row,col)) == ' #' ) count++;
69
+ }
70
+ }
71
+ return count;
72
+ }
73
+
74
+
75
+ std::string pattern_to_string (const std::unordered_map<Coord2D, char , hasher>& map) {
76
+ std::string ans = " " ;
77
+ const int n = (map.size () == 4 ) ? 2 : 3 ;
78
+ for (int row = 0 ; row < n; row++) {
79
+ for (int col = 0 ; col < n; col++) {
80
+ ans += map.at (Coord2D (row, col));
81
+ }
82
+ if (row != n - 1 ) ans += ' /' ;
83
+ }
84
+ return ans;
85
+ }
86
+
87
+ std::unordered_map<Coord2D, char , hasher> string_to_pattern (const std::string& s) {
88
+ std::unordered_map<Coord2D, char , hasher> map;
89
+ int n = 0 ;
90
+ if (s.size () == 5 ) {
91
+ n = 2 ;
92
+ } else if (s.size () == 11 ) {
93
+ n = 3 ;
94
+ } else if (s.size () == 19 ) {
95
+ n = 4 ;
96
+ }
97
+ for (int row = 0 ; row < n; row++) {
98
+ for (int col = 0 ; col < n; col++) {
99
+ map[Coord2D (row, col)] = s[row * (n + 1 ) + col]; // n+1 to include the '/'
100
+ }
101
+ }
102
+ return map;
103
+ }
104
+
105
+ std::unordered_map<Coord2D, char , hasher> rotate_pattern (const std::unordered_map<Coord2D, char , hasher>& map) {
106
+ std::unordered_map<Coord2D, char , hasher> ans;
107
+ const int n = map.size () == 4 ? 2 :3 ;
108
+ for (int row = 0 ; row < n; row++) {
109
+ for (int col = 0 ; col < n; col++) {
110
+ ans[Coord2D (row, col)] = map.at (Coord2D (n - col - 1 , row));
111
+ // std::cout << ans[Coord2D(row, col)];
112
+ }
113
+ // std::cout << '\n';
114
+ }
115
+ // std::cout << '\n';
116
+ return ans;
117
+ }
118
+
119
+ std::unordered_map<Coord2D, char , hasher> flip_pattern (const std::unordered_map<Coord2D, char , hasher>& map) {
120
+ std::unordered_map<Coord2D, char , hasher> ans;
121
+ const int n = map.size () == 4 ? 2 :3 ;
122
+ for (int row = 0 ; row < n; row++) {
123
+ for (int col = 0 ; col < n; col++) {
124
+ ans[Coord2D (n - row - 1 , col)] = map.at (Coord2D (row, col));
125
+ }
126
+ }
127
+ return ans;
128
+ }
129
+
130
+ int main (int argc, char * argv[]) {
131
+ const std::string input = (argc > 1 ) ? argv[1 ] : " ../input/day_21_input" ;
132
+ std::ifstream file (input);
133
+ std::string line;
134
+ const std::regex regex_pattern (R"( ([#./]+) => ([#./]+))" );
135
+ std::unordered_map<std::string, std::unordered_map<Coord2D, char , hasher>> rules;
136
+ while (std::getline (file, line)) {
137
+ std::smatch match;
138
+ std::regex_search (line, match, regex_pattern);
139
+ const std::string input_str = match[1 ];
140
+ // std::cout << input_str << '\n';
141
+ // std::cout << pattern_to_string(string_to_pattern(input_str)) << '\n';
142
+ assert (input_str == pattern_to_string (string_to_pattern (input_str)));
143
+ const auto output_pattern_str = match[2 ];
144
+ // std::cout << output_pattern_str << '\n';
145
+ const auto output_pattern = string_to_pattern (output_pattern_str);
146
+ auto pattern = string_to_pattern (input_str);
147
+
148
+ // rules[pattern_to_string(pattern)] = output_pattern;
149
+ // rules[pattern_to_string(flip_pattern(pattern))] = output_pattern;
150
+ for (int i = 0 ; i < 4 ; i++) {
151
+ pattern = rotate_pattern (pattern);
152
+ rules[pattern_to_string (pattern)] = output_pattern;
153
+ rules[pattern_to_string (flip_pattern (pattern))] = output_pattern;
154
+ }
155
+ }
156
+
157
+ // .#.
158
+ // ..#
159
+ // ###
160
+ std::unordered_map<Coord2D, char , hasher> pattern;
161
+ std::unordered_map<Coord2D, char , hasher> new_pattern;
162
+ pattern[Coord2D (0 ,0 )] = ' .' ;
163
+ pattern[Coord2D (0 ,1 )] = ' #' ;
164
+ pattern[Coord2D (0 ,2 )] = ' .' ;
165
+ pattern[Coord2D (1 ,0 )] = ' .' ;
166
+ pattern[Coord2D (1 ,1 )] = ' .' ;
167
+ pattern[Coord2D (1 ,2 )] = ' #' ;
168
+ pattern[Coord2D (2 ,0 )] = ' #' ;
169
+ pattern[Coord2D (2 ,1 )] = ' #' ;
170
+ pattern[Coord2D (2 ,2 )] = ' #' ;
171
+
172
+ int n_parts = 0 ;
173
+ int n = 0 ;
174
+ int iterations = 0 ;
175
+ // Fix (0,0)
176
+ for (int iterations = 0 ; iterations < 5 ; iterations++) {
177
+ const int dim = std::sqrt (pattern.size ());
178
+
179
+ if (dim % 2 == 0 ) {
180
+ // std::cout << __LINE__ << '\n';
181
+ n_parts = dim/2 ;
182
+ n = 2 ;
183
+ } else if (dim % 3 == 0 ) {
184
+ // std::cout << __LINE__ << '\n';
185
+ n_parts = dim/3 ;
186
+ n = 3 ;
187
+ } else {
188
+ std::cout << " Weird" << ' \n ' ;
189
+ std::cout << dim << ' \n ' ;
190
+ exit (0 );
191
+ }
192
+ // std::cout << "dim == " << dim << '\n';
193
+ // std::cout << "n_parts == " << n_parts << '\n';
194
+ // std::cout << "n == " << n << '\n';
195
+ // std::cout << "Pattern: " <<'\n';
196
+ // print_pattern(pattern);
197
+ for (int parts_row = 0 ; parts_row < n_parts; parts_row++) {
198
+ const int row = n * parts_row;
199
+ for (int parts_col = 0 ; parts_col < n_parts; parts_col++) {
200
+ const int col = n * parts_col;
201
+ std::unordered_map<Coord2D, char , hasher> mini_pattern;
202
+ for (int i = 0 ; i < n; i++) {
203
+ for (int j = 0 ; j < n; j++) {
204
+ mini_pattern[Coord2D (i,j)]= pattern[Coord2D (row + i, col + j)];
205
+ }
206
+ }
207
+ // std::cout << "Mini pattern: " <<'\n';
208
+ // print_pattern(mini_pattern);
209
+ const auto new_mini_pattern = rules.at (pattern_to_string (mini_pattern));
210
+ // std::cout << "New mini pattern: " <<'\n';
211
+ // print_pattern(new_mini_pattern);
212
+ for (int i = 0 ; i < n + 1 ; i++) {
213
+ for (int j = 0 ; j < n + 1 ; j++) {
214
+ new_pattern[Coord2D ((n + 1 )* parts_row + i, (n + 1 ) * parts_col + j)] = new_mini_pattern.at (Coord2D (i,j));
215
+ }
216
+ }
217
+ }
218
+ }
219
+ std::swap (pattern, new_pattern);
220
+ // std::cout << count_on_in_pattern(pattern) <<'\n';
221
+ }
222
+ // std::cout << "Pattern: " <<'\n';
223
+ // print_pattern(pattern);
224
+ std::cout << count_on_in_pattern (pattern) <<' \n ' ;
225
+ return 0 ;
226
+ }
0 commit comments