-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathDay21.java
240 lines (209 loc) · 6.19 KB
/
Day21.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package aoc17;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class Day21 {
private char[][] fractalGrid;
// rules for 2x2 grids
private Map<String, String> rulesTwo;
// rules for 3x3 grids
private Map<String, String> rulesThree;
public Day21(File input) {
rulesTwo = new HashMap<>();
rulesThree = new HashMap<>();
fillRules(input);
}
// part 1
public int numOfOnAfterN(int n) {
// initial state
fractalGrid = new char[][] { { '.', '#', '.' }, { '.', '.', '#' }, { '#', '#', '#' } };
for (int i = 0; i < n; i++) {
enhance();
}
int count = 0;
for (char[] row : fractalGrid) {
for (char c : row)
if (c == '#')
count++;
}
return count;
}
// enhances the fractal grid once (iterates once)
private void enhance() {
int currentSize = fractalGrid.length;
int subSize = currentSize % 2 == 0 ? 2 : 3;
List<char[][]> subGrids = getSubGrids(fractalGrid, subSize);
List<char[][]> enhancedSubGrids = getEnhancedSubGrids(subGrids);
// construct the final grid using the enhanced subgrids
int finalSize = currentSize + (int) Math.sqrt(enhancedSubGrids.size());
char[][] nextFractalGrid = new char[finalSize][finalSize];
int nextSubSize = enhancedSubGrids.get(0).length;
int currentGridIndex = 0;
for (int i = 0; i < finalSize; i += nextSubSize) {
for (int j = 0; j < finalSize; j += nextSubSize) {
int row = 0;
int column = 0;
for (int k = i; k < i + nextSubSize; k++) {
for (int l = j; l < j + nextSubSize; l++) {
nextFractalGrid[k][l] = enhancedSubGrids.get(currentGridIndex)[row][column++];
}
row++;
column = 0;
}
currentGridIndex++;
}
}
fractalGrid = nextFractalGrid;
}
// searches for matches in the rule lists and returns a list of enhanced
// subgrids
private List<char[][]> getEnhancedSubGrids(List<char[][]> subGrids) {
List<char[][]> enhancedGrids = new ArrayList<>();
int subSize = subGrids.get(0).length;
Map<String, String> rules = null;
if (subSize == 2)
rules = rulesTwo;
else
rules = rulesThree;
// search for a valid enhancement rule
for (char[][] subGrid : subGrids) {
boolean found = false;
// rotate original grid 4 times (one additional rotation to get it
// into the initial state)
for (int i = 0; i < 4; i++) {
String formattedGrid = formattedGrid(subGrid);
if (rules.containsKey(formattedGrid)) {
found = true;
enhancedGrids.add(parseGrid(rules.get(formattedGrid), subSize + 1));
break;
}
rotateRight(subGrid);
}
// flip the grid if no matches are found
if (!found) {
flip(subGrid);
// rotate flipped grid 3 times
for (int i = 0; i < 3; i++) {
String rotatedGrid = formattedGrid(subGrid);
if (rules.containsKey(rotatedGrid)) {
found = true;
enhancedGrids.add(parseGrid(rules.get(rotatedGrid), subSize + 1));
break;
}
rotateRight(subGrid);
}
}
}
return enhancedGrids;
}
private List<char[][]> getSubGrids(char[][] grid, int subSize) {
List<char[][]> subGrids = new ArrayList<>();
for (int i = 0; i < grid.length; i += subSize) {
for (int j = 0; j < grid.length; j += subSize) {
char[][] subGrid = new char[subSize][];
int row = 0;
int column = 0;
for (int k = i; k < i + subSize; k++) {
subGrid[row] = new char[subSize];
for (int l = j; l < j + subSize; l++) {
subGrid[row][column++] = grid[k][l];
}
row++;
column = 0;
}
subGrids.add(subGrid);
}
}
return subGrids;
}
// returns the formatted grid (rows seperated by slashes) as a grid
private char[][] parseGrid(String formattedGrid, int size) {
char[][] grid = new char[size][size];
// System.out.println(formattedGrid + " " + size);
int column = 0;
int row = 0;
for (int i = 0; i < formattedGrid.length(); i++) {
if (formattedGrid.charAt(i) == '/') {
row++;
column = 0;
} else
grid[row][column++] = formattedGrid.charAt(i);
}
return grid;
}
// returns the grid formatted as rows seperated by slashes
private String formattedGrid(char[][] grid) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid.length; j++) {
sb.append(grid[i][j]);
}
if (i < grid.length - 1)
sb.append("/");
}
return sb.toString();
}
// fills the rules lists
private void fillRules(File input) {
try {
BufferedReader br = new BufferedReader(new FileReader(input));
String line = "";
while ((line = br.readLine()) != null) {
if (line.length() > 20) {
rulesThree.put(line.substring(0, line.indexOf('=') - 1), line.substring(line.indexOf('>') + 2));
} else
rulesTwo.put(line.substring(0, line.indexOf('=') - 1), line.substring(line.indexOf('>') + 2));
}
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// rotates the grid 90‹ clockwise
public static void rotateRight(char[][] grid) {
char[][] tmpGrid = deepCopyGrid(grid);
int columnTmpGrid = 0;
int row = 0;
int column = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = grid.length - 1; j >= 0; j--) {
grid[row][column++] = tmpGrid[j][columnTmpGrid];
if (column == grid.length) {
column = 0;
row++;
columnTmpGrid++;
}
}
}
}
// flips the grid elements (reverses every row)
private static char[][] flip(char[][] grid) {
for (char[] subA : grid) {
for (int i = 0; i < grid.length / 2; i++) {
char tmp = subA[i];
subA[i] = subA[grid.length - i - 1];
subA[grid.length - i - 1] = tmp;
}
}
// Arrays.stream(grid).map(Arrays::toString).forEach(System.out::println);
return grid;
}
private static char[][] deepCopyGrid(char[][] input) {
if (input == null)
return null;
char[][] result = new char[input.length][];
for (int r = 0; r < input.length; r++) {
result[r] = input[r].clone();
}
return result;
}
public static void main(String[] args) {
Day21 test = new Day21(new File("C:\\Users\\Timucin\\Desktop\\Advent of code 2017\\Day 21\\InputFile1.txt"));
System.out.println(test.numOfOnAfterN(18));
}
}