@@ -31,7 +31,7 @@ impl Solution for Day21 {
31
31
input
32
32
. lines ( )
33
33
. map ( |line| {
34
- let path_len = self . path_len ( line, & pads) ;
34
+ let path_len = self . path ( line, & pads) . chars ( ) . count ( ) ;
35
35
let num: usize = line. trim_end_matches ( 'A' ) . parse ( ) . unwrap ( ) ;
36
36
37
37
num * path_len
@@ -46,46 +46,53 @@ impl Solution for Day21 {
46
46
}
47
47
48
48
impl Day21 {
49
- fn path_len ( & self , code : & str , pads : & Vec < Pad > ) -> usize {
50
- let mut current = code. to_string ( ) ;
51
-
52
- for pad in pads {
53
- let path = self . path_for_str ( & current, pad) ;
54
-
55
- current = path. iter ( ) . map ( |key| key. to_string ( ) ) . collect :: < String > ( ) ;
49
+ fn path ( & self , code : & str , pads : & [ Pad ] ) -> String {
50
+ if pads. is_empty ( ) {
51
+ return code. to_string ( ) ;
56
52
}
57
53
58
- current. chars ( ) . count ( )
54
+ let code = "A" . to_owned ( ) + code;
55
+ let pad = & pads[ 0 ] ;
56
+ let pad_left = & pads[ 1 ..] ;
57
+
58
+ code. chars ( )
59
+ . tuple_windows ( )
60
+ . map ( |( from, to) | {
61
+ self . all_shortest_paths_between_buttons ( from, to, pad)
62
+ . iter ( )
63
+ . map ( |path| self . path ( path, pad_left) )
64
+ . min_by_key ( |path| path. chars ( ) . count ( ) )
65
+ . unwrap ( )
66
+ } )
67
+ . collect ( )
59
68
}
60
69
61
- fn path_for_str ( & self , code : & str , pad : & Pad ) -> Vec < Key > {
62
- let code = "A" . to_owned ( ) + code;
70
+ fn all_shortest_paths_between_buttons ( & self , from : char , to : char , pad : & Pad ) -> Vec < String > {
63
71
let adjacent = pad. adjacent . clone ( ) ;
64
72
65
73
let neighbours = Box :: new ( move |p : Point | adjacent. get ( & p) . unwrap ( ) . to_vec ( ) ) ;
66
74
let distance = Box :: new ( |_, _| 1 ) ;
67
75
68
76
let dijkstra = Dijkstra :: new ( neighbours, distance) ;
69
77
70
- code. chars ( )
71
- . tuple_windows ( )
72
- . flat_map ( |( from, to) | {
73
- let start = pad. position ( from as u8 ) . unwrap ( ) ;
74
- let end = pad. position ( to as u8 ) . unwrap ( ) ;
78
+ let start = pad. position ( from as u8 ) . unwrap ( ) ;
79
+ let end = pad. position ( to as u8 ) . unwrap ( ) ;
75
80
76
- let is_end = |p : Point | p == end;
77
- let path = dijkstra. all_paths ( vec ! [ start] , & is_end) ;
81
+ let is_end = |p : Point | p == end;
82
+ let paths = dijkstra. all_paths ( vec ! [ start] , & is_end) ;
78
83
79
- let min_path = path. iter ( ) . min_by_key ( |p| p. len ( ) ) . unwrap ( ) ;
80
- let mut directions: Vec < Key > = min_path
84
+ paths
85
+ . iter ( )
86
+ . map ( |path| {
87
+ let mut directions: Vec < Key > = path
81
88
. iter ( )
82
89
. collect_vec ( )
83
90
. windows ( 2 )
84
91
. map ( |pair| Dir ( pair[ 0 ] . direction ( pair[ 1 ] ) . unwrap ( ) ) )
85
92
. collect ( ) ;
86
93
directions. push ( Activate ) ;
87
94
88
- directions. into_iter ( )
95
+ directions. iter ( ) . map ( |d| d . to_string ( ) ) . collect ( )
89
96
} )
90
97
. collect ( )
91
98
}
@@ -175,10 +182,8 @@ impl Pad {
175
182
176
183
#[ cfg( test) ]
177
184
mod tests {
178
- use crate :: solutions:: year2024:: day21:: Key :: { Activate , Dir } ;
179
185
use crate :: solutions:: year2024:: day21:: { Day21 , Pad } ;
180
186
use crate :: solutions:: Solution ;
181
- use crate :: utils:: direction:: Direction :: { East , North , South , West } ;
182
187
183
188
const EXAMPLE : & str = r#"029A
184
189
980A
@@ -187,69 +192,19 @@ mod tests {
187
192
379A"# ;
188
193
189
194
#[ test]
190
- #[ ignore]
191
195
fn part_one_example ( ) {
192
196
assert_eq ! ( "126384" , Day21 . part_one( EXAMPLE ) ) ;
193
197
}
194
198
195
199
#[ test]
196
- #[ ignore]
197
200
fn path_len ( ) {
198
201
let pads = vec ! [ Pad :: numeric( ) , Pad :: key( ) , Pad :: key( ) ] ;
199
202
200
- assert_eq ! ( 68 , Day21 . path_len( "029A" , & pads) ) ;
201
- assert_eq ! ( 60 , Day21 . path_len( "980A" , & pads) ) ;
202
- assert_eq ! ( 68 , Day21 . path_len( "179A" , & pads) ) ;
203
- assert_eq ! ( 64 , Day21 . path_len( "456A" , & pads) ) ;
204
- assert_eq ! ( 64 , Day21 . path_len( "379A" , & pads) ) ;
205
- assert_eq ! ( 78 , Day21 . path_len( "739A" , & pads) ) ;
206
- }
207
-
208
- #[ test]
209
- fn path_for_str ( ) {
210
- let numeric = & Pad :: numeric ( ) ;
211
- let key = & Pad :: key ( ) ;
212
-
213
- assert_eq ! ( Day21 . path_for_str( "AA" , numeric) , vec![ Activate , Activate ] ) ;
214
- assert_eq ! (
215
- Day21 . path_for_str( "A1" , numeric) ,
216
- vec![ Activate , Dir ( North ) , Dir ( West ) , Dir ( West ) , Activate ]
217
- ) ;
218
- assert_eq ! (
219
- Day21 . path_for_str( "A4" , numeric) ,
220
- vec![
221
- Activate ,
222
- Dir ( North ) ,
223
- Dir ( North ) ,
224
- Dir ( West ) ,
225
- Dir ( West ) ,
226
- Activate
227
- ]
228
- ) ;
229
- assert_eq ! (
230
- Day21 . path_for_str( "A7" , numeric) ,
231
- vec![
232
- Activate ,
233
- Dir ( North ) ,
234
- Dir ( North ) ,
235
- Dir ( North ) ,
236
- Dir ( West ) ,
237
- Dir ( West ) ,
238
- Activate
239
- ]
240
- ) ;
241
- assert_eq ! (
242
- Day21 . path_for_str( "<A" , key) ,
243
- vec![
244
- Dir ( South ) ,
245
- Dir ( West ) ,
246
- Dir ( West ) ,
247
- Activate ,
248
- Dir ( East ) ,
249
- Dir ( East ) ,
250
- Dir ( North ) ,
251
- Activate
252
- ]
253
- ) ;
203
+ assert_eq ! ( 68 , Day21 . path( "029A" , & pads) . len( ) ) ;
204
+ assert_eq ! ( 60 , Day21 . path( "980A" , & pads) . len( ) ) ;
205
+ assert_eq ! ( 68 , Day21 . path( "179A" , & pads) . len( ) ) ;
206
+ assert_eq ! ( 64 , Day21 . path( "456A" , & pads) . len( ) ) ;
207
+ assert_eq ! ( 64 , Day21 . path( "379A" , & pads) . len( ) ) ;
208
+ assert_eq ! ( 78 , Day21 . path( "739A" , & pads) . len( ) ) ;
254
209
}
255
210
}
0 commit comments