22
22
import com .github .pareronia .aocd .Aocd ;
23
23
import com .github .pareronia .aocd .Puzzle ;
24
24
25
- import lombok .AllArgsConstructor ;
26
- import lombok .EqualsAndHashCode ;
27
- import lombok .Getter ;
28
- import lombok .RequiredArgsConstructor ;
29
- import lombok .ToString ;
30
-
31
25
public class AoC2016_22 extends AoCBase {
32
26
33
27
private static final Pattern REGEX = Pattern .compile (
@@ -61,42 +55,42 @@ public static AoC2016_22 createDebug(final List<String> input) {
61
55
62
56
private Set <Node > getUnusableNodes () {
63
57
final Integer maxAvailable = this .nodes .stream ()
64
- .max (comparing (Node ::getAvailable ))
65
- .map (Node ::getAvailable ).orElseThrow ();
58
+ .max (comparing (Node ::available ))
59
+ .map (Node ::available ).orElseThrow ();
66
60
return this .nodes .stream ()
67
- .filter (n -> n .getUsed () > maxAvailable )
61
+ .filter (n -> n .used () > maxAvailable )
68
62
.collect (toSet ());
69
63
}
70
64
71
65
private Node getEmptyNode () {
72
66
final List <Node > emptyNodes = nodes .stream ()
73
- .filter (n -> n .getUsed () == 0 )
67
+ .filter (n -> n .used () == 0 )
74
68
.collect (toList ());
75
69
assertTrue (emptyNodes .size () == 1 , () -> "Expected 1 empty node" );
76
70
return emptyNodes .get (0 );
77
71
}
78
72
79
73
private Integer getMaxX () {
80
74
return this .nodes .stream ()
81
- .max (comparing (Node ::getX ))
82
- .map (Node ::getX ).orElseThrow ();
75
+ .max (comparing (Node ::x ))
76
+ .map (Node ::x ).orElseThrow ();
83
77
}
84
78
85
79
private Integer getMaxY () {
86
80
return this .nodes .stream ()
87
- .max (comparing (Node ::getY ))
88
- .map (Node ::getY ).orElseThrow ();
81
+ .max (comparing (Node ::y ))
82
+ .map (Node ::y ).orElseThrow ();
89
83
}
90
84
91
85
private Node getGoalNode () {
92
86
return nodes .stream ()
93
- .filter (n -> n .getX () == getMaxX () && n .getY () == 0 )
87
+ .filter (n -> n .x () == getMaxX () && n .y () == 0 )
94
88
.findFirst ().orElseThrow ();
95
89
}
96
90
97
91
private Node getAccessibleNode () {
98
92
return nodes .stream ()
99
- .filter (n -> n .getX () == 0 && n .getY () == 0 )
93
+ .filter (n -> n .x () == 0 && n .y () == 0 )
100
94
.findFirst ().orElseThrow ();
101
95
}
102
96
@@ -106,20 +100,20 @@ public Integer solvePart1() {
106
100
.filter (Node ::isNotEmpty )
107
101
.flatMap (a -> this .nodes .stream ()
108
102
.filter (b -> !a .equals (b ))
109
- .filter (b -> a .getUsed () <= b .getAvailable ()))
103
+ .filter (b -> a .used () <= b .available ()))
110
104
.count ();
111
105
}
112
106
113
107
private void visualize () {
114
108
final Integer maxX = getMaxX ();
115
109
final Integer maxY = getMaxY ();
116
110
final List <Node > sorted = this .nodes .stream ()
117
- .sorted (comparing (n -> n .getX () * maxY + n .getY ()))
111
+ .sorted (comparing (n -> n .x () * maxY + n .y ()))
118
112
.collect (toList ());
119
113
final List <List <Node >> grid = Stream .iterate (0 , i -> i <= maxX , i -> i + 1 )
120
114
.map (i -> sorted .stream ()
121
115
.skip (i * (maxY + 1 ))
122
- .takeWhile (n -> n .getX () == i )
116
+ .takeWhile (n -> n .x () == i )
123
117
.collect (toList ()))
124
118
.collect (toList ());
125
119
final Set <Node > unusableNodes = getUnusableNodes ();
@@ -147,7 +141,7 @@ private void visualize() {
147
141
}
148
142
149
143
private Position toPosition (final Node node ) {
150
- return Position .of (node .getX (), node .getY ());
144
+ return Position .of (node .x (), node .y ());
151
145
}
152
146
153
147
private Function <Path , Boolean > stopAt (
@@ -191,7 +185,7 @@ private Integer solve2() {
191
185
new PathFinder (goalNode , accessibleNode , max , unusableNodes )
192
186
.findPaths (stopAt (accessibleNode , paths ));
193
187
final Integer length = paths .stream ()
194
- .map (Path ::getLength )
188
+ .map (Path ::length )
195
189
.collect (summingInt (Integer ::valueOf ));
196
190
log (length );
197
191
return length + 1 ;
@@ -202,21 +196,21 @@ private Integer solve2Cheat() {
202
196
final Set <Node > unusableNodes = getUnusableNodes ();
203
197
log (unusableNodes );
204
198
final Set <Integer > holeYs = unusableNodes .stream ()
205
- .map (Node ::getY )
199
+ .map (Node ::y )
206
200
.collect (toSet ());
207
201
assertTrue (holeYs .size () == 1 , () -> "Expected all unusable nodes in 1 row" );
208
202
final Integer holeY = holeYs .iterator ().next ();
209
203
if (holeY <= 1 ) {
210
204
throw new IllegalStateException ("Unsolvable" );
211
205
}
212
206
assertFalse (unusableNodes .stream ()
213
- .max (comparing (Node ::getX ))
214
- .map (Node ::getX )
207
+ .max (comparing (Node ::x ))
208
+ .map (Node ::x )
215
209
.orElseThrow () != getMaxX (),
216
210
() -> "Expected unusable row to touch side" );
217
211
final Integer holeX = unusableNodes .stream ()
218
- .min (comparing (Node ::getX ))
219
- .map (Node ::getX )
212
+ .min (comparing (Node ::x ))
213
+ .map (Node ::x )
220
214
.orElseThrow ();
221
215
final Position hole = Position .of (holeX - 1 , holeY );
222
216
final Position emptyNode = toPosition (getEmptyNode ());
@@ -259,13 +253,22 @@ public static void main(final String[] args) throws Exception {
259
253
"/dev/grid/node-x2-y2 9T 6T 3T 66%"
260
254
);
261
255
262
- @ RequiredArgsConstructor
263
256
private static final class PathFinder {
264
257
private final Position start ;
265
258
private final Position destination ;
266
259
private final Position max ;
267
260
private final Set <Position > unusable ;
268
261
262
+ public PathFinder (
263
+ final Position start , final Position destination ,
264
+ final Position max , final Set <Position > unusable
265
+ ) {
266
+ this .start = start ;
267
+ this .destination = destination ;
268
+ this .max = max ;
269
+ this .unusable = unusable ;
270
+ }
271
+
269
272
public void findPaths (final Function <Path , Boolean > stop ) {
270
273
final Deque <Path > paths = new ArrayDeque <>();
271
274
Path path = new Path (0 , this .start );
@@ -278,19 +281,19 @@ public void findPaths(final Function<Path, Boolean> stop) {
278
281
}
279
282
for (final Direction direction : Direction .CAPITAL ) {
280
283
final Path newPath = buildNewPath (path , direction );
281
- if (isInBounds (newPath .getPosition ())
282
- && isUsable (newPath .getPosition ())
283
- && !seen .contains (newPath .getPosition ())) {
284
+ if (isInBounds (newPath .position ())
285
+ && isUsable (newPath .position ())
286
+ && !seen .contains (newPath .position ())) {
284
287
paths .add (newPath );
285
- seen .add (newPath .getPosition ());
288
+ seen .add (newPath .position ());
286
289
}
287
290
}
288
291
}
289
292
}
290
293
291
294
private Path buildNewPath (final Path path , final Direction direction ) {
292
- return new Path (path .getLength () + 1 ,
293
- path .getPosition ().translate (direction ));
295
+ return new Path (path .length () + 1 ,
296
+ path .position ().translate (direction ));
294
297
}
295
298
296
299
private boolean isInBounds (final Position position ) {
@@ -305,37 +308,13 @@ private boolean isUsable(final Point position) {
305
308
}
306
309
}
307
310
308
- @ RequiredArgsConstructor
309
- @ EqualsAndHashCode
310
- @ ToString
311
- private static final class Path {
312
- @ Getter
313
- private final Integer length ;
314
- @ Getter
315
- private final Position position ;
316
-
311
+ record Path (int length , Position position ) {
317
312
public boolean isAt (final Position position ) {
318
313
return this .position .equals (position );
319
314
}
320
315
}
321
-
322
- @ AllArgsConstructor
323
- @ EqualsAndHashCode (onlyExplicitlyIncluded = true )
324
- @ ToString (onlyExplicitlyIncluded = true )
325
- private static final class Node {
326
- @ Getter
327
- @ EqualsAndHashCode .Include
328
- @ ToString .Include
329
- private final Integer x ;
330
- @ Getter
331
- @ EqualsAndHashCode .Include
332
- @ ToString .Include
333
- private final Integer y ;
334
- @ Getter
335
- private final Integer used ;
336
- @ Getter
337
- private final Integer available ;
338
-
316
+
317
+ record Node (int x , int y , int used , int available ) {
339
318
public boolean isNotEmpty () {
340
319
return this .used != 0 ;
341
320
}
0 commit comments