-
Notifications
You must be signed in to change notification settings - Fork 0
/
day03.groovy
139 lines (114 loc) · 3.56 KB
/
day03.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
129
130
131
132
133
134
135
136
137
138
139
import groovy.transform.TupleConstructor;
def input = new File("input/day03.txt").readLines();
@TupleConstructor
class PartNumber {
Schematic schematic;
int x;
int y;
int len;
int value;
boolean isValid() {
int x0 = Math.max(0, x - 1);
int x1 = Math.min(schematic.width - 1, x + len + 1);
int y0 = Math.max(0, y - 1);
int y1 = Math.min(schematic.height - 1, y + 1);
for (int j in y0..y1) {
for (int i in x0..x1) {
char c = schematic.get(i, j);
if (!c.isDigit() && c != '.') {
return true;
}
}
}
return false;
}
boolean includes(int px, int py) {
int x0 = Math.max(0, x - 1);
int x1 = Math.min(schematic.width - 1, x + len + 1);
int y0 = Math.max(0, y - 1);
int y1 = Math.min(schematic.height - 1, y + 1);
return x0 <= px && px <= x1 && y0 <= py && py <= y1;
}
String toString() {
int x0 = Math.max(0, x - 1);
int x1 = Math.min(schematic.width - 1, x + len + 1);
int y0 = Math.max(0, y - 1);
int y1 = Math.min(schematic.height - 1, y + 1);
def result = "";
for (int j in y0..y1) {
for (int i in x0..x1) {
result += schematic.get(i, j);
}
result += "\n";
}
return result;
}
}
class Schematic {
private final char[] arr;
final int width;
final int height;
private def partNumbersCache;
Schematic(List<String> input) {
arr = input.join("").toCharArray();
width = input[0].size();
height = input.size();
}
def get(int x, int y) {
int pos = x + y * width;
return arr[pos];
}
def getPartNumbers() {
if (partNumbersCache != null) {
return partNumbersCache;
}
def result = [];
def numberIndices = arr.findIndexValues { it.isDigit() };
int pnStart = numberIndices[0];
int curr, next;
for (int i = 0; i < numberIndices.size(); i++) {
curr = numberIndices[i];
next = numberIndices[i + 1] ?: -1;
if (next - curr == 1) {
continue;
}
int pnX = pnStart % width;
int pnY = Math.floor(pnStart / width);
def pnEnd = curr;
def pnLength = pnEnd - pnStart;
result << new PartNumber(this, pnX, pnY, pnLength, arr[pnStart..pnEnd].join("").toInteger());
pnStart = next;
}
partNumbersCache = result;
return result;
}
def getGears() {
def gearIndices = arr.findIndexValues { it == '*' };
return gearIndices.collect {
int gX = it % width;
int gY = Math.floor(it / width);
return getPartNumbers().findAll { pn ->
return pn.includes(gX, gY);
};
}.findAll { pnc -> pnc.size() == 2 };
}
String toString() {
def result = "";
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
result += this.get(x, y);
}
result += "\n";
}
return result;
}
}
def schematic = new Schematic(input);
def partNumberSum = schematic.getPartNumbers().inject(0) { acc, it ->
return it.isValid() ? acc + it.value : acc;
};
println(partNumberSum);
def gearRatioSum = schematic.getGears().inject(0) { acc, it ->
return acc + (it[0].value * it[1].value);
};
println(gearRatioSum);