-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday21.groovy
128 lines (107 loc) · 3.05 KB
/
day21.groovy
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
import groovy.time.TimeCategory;
import groovy.time.TimeDuration;
import groovy.transform.EqualsAndHashCode;
import groovy.transform.ToString;
import groovy.transform.TupleConstructor;
@EqualsAndHashCode
@ToString
@TupleConstructor
class Pos {
final int x;
final int y;
}
@EqualsAndHashCode
class Map {
char[] arr;
int width;
int height;
Map(List<String> input) {
this.arr = input.join("").toCharArray();
this.width = input[0].size();
this.height = input.size();
}
def getAt(Pos pos) {
def x = Math.floorMod(pos.x, width);
def y = Math.floorMod(pos.y, height);
int arrpos = x + y * width;
return arr[arrpos];
}
def putAt(Pos pos, char value) {
def x = Math.floorMod(pos.x, width);
def y = Math.floorMod(pos.y, height);
int arrpos = x + y * width;
arr[arrpos] = value;
}
def posOf(char c) {
return arr.findIndexValues { it == c }.collect {
new Pos(it % width as int, Math.floor(it / width) as int)
};
}
String toString() {
def result = "";
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
result += this[new Pos(x, y)];
}
result += "\n";
}
return result;
}
}
assert new Map(['...', '...', '...']) == new Map(['...', '...', '...']);
assert new Map(['...', '...', '...']) != new Map(['...', '.S.', '...']);
@EqualsAndHashCode
@ToString
@TupleConstructor
class State {
final Pos pos;
final int step;
State[] nexts() {
return [
new State(new Pos(pos.x + 1, pos.y), step + 1),
new State(new Pos(pos.x - 1, pos.y), step + 1),
new State(new Pos(pos.x, pos.y + 1), step + 1),
new State(new Pos(pos.x, pos.y - 1), step + 1),
];
}
}
def input = new File("input/day21.txt").readLines();
def map = new Map(input);
def center = map.posOf('S' as char)[0];
// map[center] = '.' as char;
// println(map);
def frontier = [];
frontier << new State(center, 0);
def reached = [:];
//reached[center] = 0;
def maxSteps = 400;
while (frontier.size() > 0) {
def curr = frontier.pop();
for (def next in curr.nexts()) {
if (
map[next.pos] != '#' as char &&
next.step <= maxSteps &&
reached[next.pos] == null
) {
frontier << next;
reached[next.pos] = next.step;
}
}
}
def countPlots(def reached, int step) {
return reached.findAll { it.value % 2 == step % 2 && it.value <= step }.size();
}
// Part 1
println(countPlots(reached, 64));
// Part 2
// Some mathematical magic (see: Lagrange interpolation polynomial)
def halfWidth = (map.width - 1) / 2 as int;
def p = countPlots(reached, halfWidth);
def q = countPlots(reached, halfWidth + map.width);
def r = countPlots(reached, halfWidth + map.width * 2);
// println("$p, $q, $r")
def a = (p - 2 * q + r) / 2;
def b = (-3 * p + 4 * q - r) / 2;
def c = p;
int x = (26501365 / map.width);
println(a * x * x + b * x + c);