4
4
import lombok .Setter ;
5
5
import org .jgrapht .Graph ;
6
6
import org .jgrapht .alg .interfaces .ShortestPathAlgorithm ;
7
- import org .jgrapht .alg .shortestpath .AStarShortestPath ;
7
+ import org .jgrapht .alg .shortestpath .DijkstraShortestPath ;
8
8
import org .jgrapht .graph .DefaultWeightedEdge ;
9
9
import org .jgrapht .graph .builder .GraphTypeBuilder ;
10
10
@@ -26,12 +26,8 @@ public Root(List<Code> codes) {
26
26
}
27
27
28
28
private RequestHandler getRequestHandler () {
29
- Robot robotDegrees = new Robot ();
30
- Robot robotRadiation = new Robot ();
31
29
Digicode digicodeDepressurized = new Digicode ();
32
-
33
- robotDegrees .setNext (robotRadiation );
34
- robotRadiation .setNext (digicodeDepressurized );
30
+ Robot robot1 = new Robot (digicodeDepressurized );
35
31
36
32
return digicodeDepressurized ;
37
33
}
@@ -90,7 +86,7 @@ public static abstract class AbstractKeypad extends RequestHandler {
90
86
91
87
private final String [][] keypad ;
92
88
93
- private final Map <String , Point > buttons ;
89
+ protected final Map <String , Point > buttons ;
94
90
95
91
private final Rectangle bounds ;
96
92
@@ -99,20 +95,20 @@ public static abstract class AbstractKeypad extends RequestHandler {
99
95
100
96
private final Point position ;
101
97
102
- private AbstractKeypad previous ;
98
+ protected AbstractKeypad previous ;
103
99
104
100
public AbstractKeypad (String [][] keypad , AbstractKeypad previous ) {
105
- this (keypad );
106
- this .previous = previous ;
107
- }
108
-
109
- public AbstractKeypad (String [][] keypad ) {
110
101
this .keypad = keypad ;
102
+ this .previous = previous ;
111
103
this .buttons = buildButtons ();
112
104
this .position = new Point (buttons .get ("A" ));
113
105
this .bounds = new Rectangle (keypad [0 ].length , keypad .length );
114
106
this .graph = buildGraph ();
115
- this .shortestPathAlgorithm = new AStarShortestPath <>(graph , (b1 , b2 ) -> buttons .get (b1 .key ).distance (buttons .get (b2 .key )));
107
+ this .shortestPathAlgorithm = new DijkstraShortestPath <>(graph );
108
+ }
109
+
110
+ public AbstractKeypad (String [][] keypad ) {
111
+ this (keypad , null );
116
112
}
117
113
118
114
private String getKeyAt (Point position ) {
@@ -130,7 +126,7 @@ private Map<String, Point> buildButtons() {
130
126
return buttons ;
131
127
}
132
128
133
- private Map <Direction , String > getNeighbours (Point position ) {
129
+ protected Map <Direction , String > getNeighbours (Point position ) {
134
130
return Arrays .stream (Direction .values ())
135
131
.filter (d -> {
136
132
Point p = d .move (position );
@@ -139,7 +135,7 @@ private Map<Direction, String> getNeighbours(Point position) {
139
135
.collect (Collectors .toMap (Function .identity (), d -> getKeyAt (d .move (position ))));
140
136
}
141
137
142
- private Graph <DepthVertex , KeyEdge > createEmptyGraph () {
138
+ protected Graph <DepthVertex , KeyEdge > createEmptyGraph () {
143
139
return GraphTypeBuilder .<DepthVertex , KeyEdge >directed ()
144
140
.allowingMultipleEdges (false )
145
141
.allowingSelfLoops (false )
@@ -148,7 +144,7 @@ private Graph<DepthVertex, KeyEdge> createEmptyGraph() {
148
144
.buildGraph ();
149
145
}
150
146
151
- private Graph <DepthVertex , KeyEdge > buildGraph () {
147
+ protected Graph <DepthVertex , KeyEdge > buildGraph () {
152
148
Graph <DepthVertex , KeyEdge > graph = Optional .ofNullable (previous ).map (p -> p .graph ).orElse (createEmptyGraph ());
153
149
154
150
int pressedLayer = graph .vertexSet ().stream ().mapToInt (DepthVertex ::depth ).max ().orElse (-1 ) + 1 ;
@@ -157,12 +153,24 @@ private Graph<DepthVertex, KeyEdge> buildGraph() {
157
153
// Layer 0 : The pressed button
158
154
buttons .keySet ().stream ().map (k -> new DepthVertex (k , pressedLayer )).forEach (graph ::addVertex );
159
155
160
- // Last layer of the previous graph are all connected to the "A" pressed layer
161
- graph .vertexSet ().stream ().filter (v -> Objects .equals (v .depth (), pressedLayer - 1 )).forEach (v -> graph .addEdge (v , new DepthVertex ("A" , pressedLayer ), new KeyEdge ()));
162
-
163
156
// Layer 1 : The released button (position of the arm)
164
157
buttons .keySet ().stream ().map (k -> new DepthVertex (k , releasedLayer )).forEach (graph ::addVertex );
165
158
159
+ // Before adding the edges between the pressed and released buttons, we need to replace all the edges from the previous graph
160
+ List <KeyEdge > edges = graph .edgeSet ().stream ().filter (e -> Objects .nonNull (e .getKey ())).toList ();
161
+
162
+ edges .forEach (e -> {
163
+ if (Objects .equals (e .getKey (), "A" )) {
164
+ graph .addEdge (new DepthVertex ("A" , pressedLayer ), graph .getEdgeTarget (e ), new KeyEdge ("A" , 1 ));
165
+ } else {
166
+ graph .addEdge (new DepthVertex (e .getKey (), pressedLayer ), graph .getEdgeTarget (e ));
167
+ }
168
+ graph .removeEdge (e );
169
+ });
170
+
171
+ // Last layer of the previous graph are all connected to the "A" pressed layer
172
+ graph .vertexSet ().stream ().filter (v -> Objects .equals (v .depth (), pressedLayer - 1 )).forEach (v -> graph .addEdge (v , new DepthVertex ("A" , pressedLayer ), new KeyEdge ()));
173
+
166
174
// Add the edges between the pressed and released buttons
167
175
// Going from pressed to released cost 0
168
176
buttons .keySet ().forEach (n -> graph .addEdge (new DepthVertex (n , pressedLayer ), new DepthVertex (n , releasedLayer ), new KeyEdge ()));
@@ -209,6 +217,38 @@ public Digicode() {
209
217
{null , "0" , "A" }
210
218
});
211
219
}
220
+
221
+ protected Graph <DepthVertex , KeyEdge > buildGraph () {
222
+ Graph <DepthVertex , KeyEdge > graph = createEmptyGraph ();
223
+
224
+ int pressedLayer = 0 ;
225
+ int releasedLayer = 1 ;
226
+
227
+ // Layer 0 : The pressed button
228
+ buttons .keySet ().stream ().map (k -> new DepthVertex (k , pressedLayer )).forEach (graph ::addVertex );
229
+
230
+ // Layer 1 : The released button (position of the arm)
231
+ buttons .keySet ().stream ().map (k -> new DepthVertex (k , releasedLayer )).forEach (graph ::addVertex );
232
+
233
+ // Add the edges between the pressed and released buttons
234
+ // Going from pressed to released cost 0
235
+ buttons .keySet ().forEach (n -> graph .addEdge (new DepthVertex (n , pressedLayer ), new DepthVertex (n , releasedLayer ), new KeyEdge ()));
236
+ // Going from released to pressed cost 1 (A)
237
+ buttons .keySet ().forEach (n -> graph .addEdge (new DepthVertex (n , releasedLayer ), new DepthVertex (n , pressedLayer ), new KeyEdge ("A" , 1 )));
238
+
239
+ // Add the edges between the released buttons
240
+ buttons .forEach ((key , position ) ->
241
+ getNeighbours (position ).forEach ((direction , neighbourKey ) ->
242
+ graph .addEdge (
243
+ new DepthVertex (key , releasedLayer ),
244
+ new DepthVertex (neighbourKey , releasedLayer ),
245
+ new KeyEdge (direction .symbol , releasedLayer ))
246
+ )
247
+ );
248
+
249
+ return graph ;
250
+ }
251
+
212
252
}
213
253
214
254
public static class Robot extends AbstractKeypad {
@@ -219,12 +259,86 @@ public Robot() {
219
259
{"<" , "v" , ">" },
220
260
});
221
261
}
262
+
263
+ public Robot (AbstractKeypad previous ) {
264
+ super (new String [][]{
265
+ {null , "^" , "A" },
266
+ {"<" , "v" , ">" },
267
+ }, previous );
268
+ }
269
+
270
+ protected Graph <DepthVertex , KeyEdge > buildGraph () {
271
+ Graph <DepthVertex , KeyEdge > graph = Optional .ofNullable (previous ).map (p -> p .graph ).orElse (createEmptyGraph ());
272
+
273
+ int precedingLayer = graph .vertexSet ().stream ().mapToInt (DepthVertex ::depth ).max ().orElseThrow (); // 1
274
+ //int pressedLayer = precedingLayer + 1; // 2
275
+ int currentLayer = precedingLayer + 1 ; // 3
276
+
277
+ // Before adding the edges between the pressed and released buttons, we need to replace all the edges from the previous graph
278
+ List <KeyEdge > edges = graph .edgeSet ().stream ().toList ();
279
+
280
+ edges .stream ().filter (e -> Objects .nonNull (e .getKey ())).forEach (e -> { // Edge <
281
+ DepthVertex source = graph .getEdgeSource (e ); // source A
282
+ DepthVertex target = graph .getEdgeTarget (e ); // target 0
283
+
284
+ {
285
+ // < A
286
+ graph .addVertex (new DepthVertex (e .getKey (), currentLayer , source .key ()));
287
+ // graph.addVertex(new DepthVertex(e.getKey(), pressedLayer, source.key()));
288
+ // graph.addEdge(new DepthVertex(e.getKey(), currentLayer, source.key()), new DepthVertex(e.getKey(), pressedLayer, source.key()), new KeyEdge("A", 1));
289
+
290
+ // < 0
291
+ graph .addVertex (new DepthVertex (e .getKey (), currentLayer , target .key ()));
292
+ // graph.addVertex(new DepthVertex(e.getKey(), pressedLayer, target.key()));
293
+ // graph.addEdge(new DepthVertex(e.getKey(), currentLayer, target.key()), new DepthVertex(e.getKey(), pressedLayer, target.key()), new KeyEdge("A", 1));
294
+
295
+ // A <
296
+ graph .addVertex (new DepthVertex (source .key (), source .depth (), e .getKey ()));
297
+
298
+ // 0 <
299
+ graph .addVertex (new DepthVertex (target .key (), target .depth (), e .getKey ()));
300
+
301
+ // < A pressed 0 <
302
+ if (Objects .equals (source .depth (), target .depth ())) {
303
+ graph .addEdge (new DepthVertex (e .getKey (), currentLayer , source .key ()), new DepthVertex (e .getKey (), currentLayer , target .key ()), new KeyEdge ("A" , 1 ));
304
+ } else {
305
+ graph .addEdge (new DepthVertex (e .getKey (), currentLayer , source .key ()), new DepthVertex (target .key (), target .depth ()), new KeyEdge ("A" , 1 ));
306
+ }
307
+ }
308
+
309
+ graph .removeEdge (e );
310
+ });
311
+
312
+
313
+ graph .vertexSet ().stream ().filter (v -> Objects .equals (v .depth (), currentLayer ))
314
+ // .filter(v -> buttons.containsKey(v.key()))
315
+ .forEach (v -> {
316
+ getNeighbours (buttons .get (v .key ())).forEach ((direction , neighbourKey ) -> {
317
+ graph .addEdge (v , new DepthVertex (neighbourKey , currentLayer , v .origin ()), new KeyEdge (direction .symbol , currentLayer ));
318
+ });
319
+
320
+ });
321
+
322
+ edges .stream ().filter (e -> Objects .isNull (e .getKey ())).forEach (e -> {
323
+ DepthVertex source = graph .getEdgeSource (e ); // source A
324
+ DepthVertex target = graph .getEdgeTarget (e ); // target 0
325
+ // Last layer of the previous graph are all connected to the "A" pressed layer
326
+ graph .addEdge (source , new DepthVertex ("A" , currentLayer , source .key ()), new KeyEdge ());
327
+ graph .removeEdge (e );
328
+ });
329
+
330
+ return graph ;
331
+ }
222
332
}
223
333
224
- public record DepthVertex (String key , int depth ) {
334
+ public record DepthVertex (String key , int depth , String origin ) {
225
335
226
336
public DepthVertex (String key ) {
227
- this (key , 0 );
337
+ this (key , 0 , null );
338
+ }
339
+
340
+ public DepthVertex (String key , int depth ) {
341
+ this (key , depth , null );
228
342
}
229
343
230
344
}
0 commit comments