@@ -31,7 +31,7 @@ impl Solution for Day21 {
3131 input
3232 . lines ( )
3333 . map ( |line| {
34- let path_len = self . path_len ( line, & pads) ;
34+ let path_len = self . path ( line, & pads) . chars ( ) . count ( ) ;
3535 let num: usize = line. trim_end_matches ( 'A' ) . parse ( ) . unwrap ( ) ;
3636
3737 num * path_len
@@ -46,46 +46,53 @@ impl Solution for Day21 {
4646}
4747
4848impl 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 ( ) ;
5652 }
5753
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 ( )
5968 }
6069
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 > {
6371 let adjacent = pad. adjacent . clone ( ) ;
6472
6573 let neighbours = Box :: new ( move |p : Point | adjacent. get ( & p) . unwrap ( ) . to_vec ( ) ) ;
6674 let distance = Box :: new ( |_, _| 1 ) ;
6775
6876 let dijkstra = Dijkstra :: new ( neighbours, distance) ;
6977
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 ( ) ;
7580
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) ;
7883
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
8188 . iter ( )
8289 . collect_vec ( )
8390 . windows ( 2 )
8491 . map ( |pair| Dir ( pair[ 0 ] . direction ( pair[ 1 ] ) . unwrap ( ) ) )
8592 . collect ( ) ;
8693 directions. push ( Activate ) ;
8794
88- directions. into_iter ( )
95+ directions. iter ( ) . map ( |d| d . to_string ( ) ) . collect ( )
8996 } )
9097 . collect ( )
9198 }
@@ -175,10 +182,8 @@ impl Pad {
175182
176183#[ cfg( test) ]
177184mod tests {
178- use crate :: solutions:: year2024:: day21:: Key :: { Activate , Dir } ;
179185 use crate :: solutions:: year2024:: day21:: { Day21 , Pad } ;
180186 use crate :: solutions:: Solution ;
181- use crate :: utils:: direction:: Direction :: { East , North , South , West } ;
182187
183188 const EXAMPLE : & str = r#"029A
184189980A
@@ -187,69 +192,19 @@ mod tests {
187192379A"# ;
188193
189194 #[ test]
190- #[ ignore]
191195 fn part_one_example ( ) {
192196 assert_eq ! ( "126384" , Day21 . part_one( EXAMPLE ) ) ;
193197 }
194198
195199 #[ test]
196- #[ ignore]
197200 fn path_len ( ) {
198201 let pads = vec ! [ Pad :: numeric( ) , Pad :: key( ) , Pad :: key( ) ] ;
199202
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( ) ) ;
254209 }
255210}
0 commit comments