10
10
import java .util .LinkedList ;
11
11
import java .util .List ;
12
12
import java .util .Map ;
13
+ import java .util .Set ;
13
14
import java .util .stream .Collectors ;
14
15
import java .util .stream .IntStream ;
15
16
import java .util .stream .Stream ;
@@ -48,13 +49,17 @@ public String getAction(Button target) {
48
49
}
49
50
throw new RuntimeException ("buttons aren't adjacent in getAction=" + this + "," + target );
50
51
}
52
+
53
+ public String toString () {
54
+ return symbol + "(" + pos .x () + "," + pos .y () + ")" ;
55
+ }
51
56
}
52
57
53
58
public record Move (Button from , Button to ) {
54
59
55
60
}
56
61
57
- public record ShortestPaths (Button source , Map <Button , Integer > dist , Map <Button , Button > prev ) {
62
+ public record ShortestPaths (Button source , Map <Button , Integer > dist , Map <Button , Set < Button > > prev ) {
58
63
59
64
// Dijkstra, yet again.
60
65
// this is probably overkill since there's not weighted edges in the graph
@@ -65,7 +70,7 @@ record ButtonWithDist(Button button, int dist) {
65
70
66
71
}
67
72
var dist = new HashMap <Button , Integer >();
68
- var prev = new HashMap <Button , Button >();
73
+ var prev = new HashMap <Button , Set < Button > >();
69
74
var q = new HashSet <Button >();
70
75
71
76
for (var button : buttons ) {
@@ -88,41 +93,66 @@ record ButtonWithDist(Button button, int dist) {
88
93
89
94
for (var v : neighborsInQ ) {
90
95
var alt = dist .get (u ) + 1 ;
91
- if (alt < dist .get (v )) {
96
+ if (alt <= dist .get (v )) {
92
97
dist .put (v , alt );
93
- prev .put (v , u );
98
+ if (!prev .containsKey (v )) {
99
+ prev .put (v , new HashSet <>());
100
+ }
101
+ prev .get (v ).add (u );
94
102
}
95
103
}
96
104
}
97
105
return new ShortestPaths (source , dist , prev );
98
106
}
99
107
100
- public List <Button > getPath (Button target ) {
101
- var s = new LinkedList <Button >();
102
- var u = target ;
103
- if (prev .containsKey (u ) || u .equals (source )) {
104
- while (u != null ) {
105
- s .addFirst (u );
106
- u = prev .get (u );
108
+ /**
109
+ * get all the possible paths for navigating from source to target
110
+ */
111
+ public List <List <Button >> getPaths (Button target ) {
112
+ var paths = new ArrayList <List <Button >>();
113
+ paths .add (new LinkedList <>(List .of (target )));
114
+ var finalPaths = new ArrayList <List <Button >>();
115
+ while (!paths .isEmpty ()) {
116
+ var newPaths = new ArrayList <List <Button >>();
117
+ for (var path : paths ) {
118
+ var u = path .getFirst ();
119
+ if (prev .containsKey (u )){
120
+ var allPrev = prev .get (u );
121
+ for (var prevItem : allPrev ) {
122
+ var newPath = new LinkedList <>(path );
123
+ newPath .addFirst (prevItem );
124
+ newPaths .add (newPath );
125
+ }
126
+
127
+ } else if (u .equals (source )) {
128
+ finalPaths .add (path );
129
+ }
107
130
}
131
+ paths = newPaths ;
108
132
}
109
- return s ;
133
+ //System.out.println(source + "->" + target + ", returning " + finalPaths.size() + " finalPaths=" + finalPaths);
134
+ return finalPaths ;
110
135
}
111
136
112
- public String getPresses (Button target ) {
113
- var path = getPath (target );
114
- var result = IntStream .range (1 , path .size ()).boxed ()
115
- .collect (foldLeft (
116
- StringBuilder ::new ,
117
- (acc , i ) -> {
118
- var button = path .get (i );
119
- var prevButton = path .get (i -1 );
120
- var action = prevButton .getAction (button );
121
- acc .append (action );
122
- return acc ;
123
- })
124
- );
125
- return result .append ("A" ).toString ();
137
+ public List <String > getPossiblePressSequences (Button target ) {
138
+ var paths = getPaths (target );
139
+ return paths .stream ()
140
+ .map (path -> {
141
+ return IntStream .range (1 , path .size ()).boxed ()
142
+ .collect (foldLeft (
143
+ StringBuilder ::new ,
144
+ (acc , i ) -> {
145
+ var button = path .get (i );
146
+ var prevButton = path .get (i - 1 );
147
+ var action = prevButton .getAction (button );
148
+ acc .append (action );
149
+ return acc ;
150
+ })
151
+ )
152
+ .append ("A" )
153
+ .toString ();
154
+ })
155
+ .toList ();
126
156
}
127
157
}
128
158
@@ -131,7 +161,7 @@ public static class Keypad {
131
161
132
162
private final Map <String , Button > buttonsMap ;
133
163
134
- private final Map <Move , String > movesToPaths ;
164
+ private final Map <Move , List < String > > movesToPaths ;
135
165
136
166
public Keypad (List <Button > buttons ) {
137
167
this .buttons = buttons ;
@@ -143,8 +173,8 @@ public Keypad(List<Button> buttons) {
143
173
this .movesToPaths = createShortestPaths ();
144
174
}
145
175
146
- private Map <Move , String > createShortestPaths () {
147
- Map <Move , String > result = new HashMap <>();
176
+ private Map <Move , List < String > > createShortestPaths () {
177
+ Map <Move , List < String > > result = new HashMap <>();
148
178
149
179
// generate graph of adjacent buttons
150
180
var graph = new HashMap <Button , List <Button >>();
@@ -171,7 +201,8 @@ private Map<Move, String> createShortestPaths() {
171
201
var shortestPaths = ShortestPaths .create (buttons , graph , button1 );
172
202
var otherButtons = buttons .stream ().filter (b -> !b .equals (button1 )).toList ();
173
203
for (var button2 : otherButtons ) {
174
- var presses = shortestPaths .getPresses (button2 );
204
+ var presses = shortestPaths .getPossiblePressSequences (button2 );
205
+ //System.out.println("move " + button1 + "->" + button2 + " adding presses=" + presses);
175
206
result .put (new Move (button1 , button2 ), presses );
176
207
}
177
208
}
@@ -182,7 +213,7 @@ public Map<String, Button> getButtonsMap() {
182
213
return buttonsMap ;
183
214
}
184
215
185
- public Map <Move , String > getMovesToPaths () {
216
+ public Map <Move , List < String > > getMovesToPaths () {
186
217
return movesToPaths ;
187
218
}
188
219
}
@@ -197,22 +228,38 @@ public KeypadNavigator(Keypad keypad, String current) {
197
228
this .current = this .keypad .getButtonsMap ().get (current );
198
229
}
199
230
200
- public String getPresses (String seq ) {
201
- StringBuilder presses = new StringBuilder ();
231
+ public List <String > getPossiblePressSequences (String seq ) {
232
+ List <StringBuilder > pressSeqList = new ArrayList <>();
233
+ pressSeqList .add (new StringBuilder ());
202
234
var c = current ;
203
235
while (!seq .isEmpty ()) {
236
+ var newPressSeqList = new ArrayList <StringBuilder >();
204
237
var symbol = seq .substring (0 , 1 );
205
238
var next = keypad .getButtonsMap ().get (symbol );
206
239
if (next .equals (c )) {
207
- presses .append ("A" );
240
+ for (var pressSeq : pressSeqList ) {
241
+ pressSeq .append ("A" );
242
+ newPressSeqList .add (pressSeq );
243
+ }
208
244
} else {
209
245
var move = new Move (c , next );
210
- presses .append (keypad .getMovesToPaths ().get (move ));
246
+ var paths = keypad .getMovesToPaths ().get (move );
247
+ for (var pressSeq : pressSeqList ) {
248
+ for (var path : paths ) {
249
+ var copy = new StringBuilder (pressSeq .toString ());
250
+ copy .append (path );
251
+ //System.out.println("move " + move + ", appended " + path + ", copy is: " + copy);
252
+ newPressSeqList .add (copy );
253
+ }
254
+ }
211
255
}
256
+ pressSeqList = newPressSeqList ;
212
257
c = next ;
213
258
seq = seq .substring (1 );
214
259
}
215
- return presses .toString ();
260
+ return pressSeqList .stream ()
261
+ .map (StringBuilder ::toString )
262
+ .toList ();
216
263
}
217
264
218
265
}
@@ -281,31 +328,59 @@ public String solve(Stream<String> data) {
281
328
new DirectionalKeypadNavigator ("A" )
282
329
);
283
330
284
- record SeqWithFinalPresses (String seq , String finalPresses ) {
285
-
286
- }
287
-
288
- var total = data
331
+ var complexities = data
289
332
.map (seq -> {
290
- var presses = seq ;
333
+ System .out .println ("doing " + seq );
334
+ // run each sequence through a list of navigators, collecting results
335
+ var pressesList = List .of (seq );
291
336
for (var navigator : navigators ) {
292
- presses = navigator .getPresses (presses );
293
- var aCount = presses .chars ().filter (ch -> ((char ) ch ) == 'A' ).count ();
294
- System .out .println (presses + " num A's=" + aCount );
337
+ var newPressesList = new ArrayList <String >();
338
+ for (var presses : pressesList ) {
339
+ var possiblePresses = navigator .getPossiblePressSequences (presses );
340
+ for (var p : possiblePresses ) {
341
+ System .out .println (p );
342
+ }
343
+ newPressesList .addAll (possiblePresses );
344
+ }
345
+
346
+ // var lengthCounts = newPressesList.stream()
347
+ // .collect(Collectors.toMap(
348
+ // String::length,
349
+ // s -> 1,
350
+ // Integer::sum
351
+ // ));
352
+ // for(var len : lengthCounts.keySet().stream().sorted(Integer::compareTo).toList()) {
353
+ // System.out.println("press sequences with len = " + len +
354
+ // " occurred " + lengthCounts.get(len) + " times");
355
+ // }
356
+
357
+ // group press sequences by their "signature" (where/which elements repeat)
358
+
359
+
360
+ System .out .println (navigator + " found " + newPressesList .size () + " possible presses" );
361
+
362
+ pressesList = newPressesList ;
295
363
}
296
- return new SeqWithFinalPresses (seq , presses );
364
+ System .out .println ("found " + pressesList .size () + " possible presses for last navigator" );
365
+ // find the shortest path of the LAST navigator only
366
+ var shortestPress = pressesList .stream ()
367
+ .min (Comparator .comparingInt (String ::length ))
368
+ .orElseThrow ();
369
+ System .out .println ("shortest press found is " + shortestPress .length () + " long" );
370
+ var result = shortestPress .length () * getNumericPortion (seq );
371
+ return result ;
297
372
})
298
- .map (s -> s .finalPresses .length () * getNumericPortion (s .seq ))
299
- .mapToInt (i -> i )
300
- .sum ();
373
+ .toList ();
301
374
375
+ var total = complexities .stream ().mapToInt (i -> i ).sum ();
302
376
return String .valueOf (total );
303
377
}
304
378
305
379
@ Override
306
380
public String solve () {
307
381
Assert .assertEquals ("126384" , solve (getSampleInput ()));
308
- return solve (getInput ());
382
+ //return solve(getInput());
383
+ return "" ;
309
384
}
310
385
311
386
public static void main (String [] args ) {
0 commit comments