@@ -7,9 +7,11 @@ use crate::utils::point::Point;
7
7
use itertools:: Itertools ;
8
8
use std:: collections:: HashMap ;
9
9
use std:: fmt:: { Display , Formatter } ;
10
+ use std:: iter:: repeat;
10
11
11
12
type Positions = HashMap < u8 , Point > ;
12
13
type Adjacent = HashMap < Point , Vec < Point > > ;
14
+ type Memo = HashMap < ( char , char , usize ) , String > ;
13
15
14
16
const NUM_PAD : & str = r#"789
15
17
456
@@ -26,27 +28,33 @@ pub struct Day21;
26
28
27
29
impl Solution for Day21 {
28
30
fn part_one ( & self , input : & str ) -> String {
29
- let pads = vec ! [ Pad :: numeric( ) , Pad :: key( ) , Pad :: key( ) ] ;
31
+ self . solve ( input, 2 ) . to_string ( )
32
+ }
33
+
34
+ fn part_two ( & self , input : & str ) -> String {
35
+ self . solve ( input, 25 ) . to_string ( )
36
+ }
37
+ }
38
+
39
+ impl Day21 {
40
+ fn solve ( & self , input : & str , keypad_count : usize ) -> usize {
41
+ let mut pads = vec ! [ Pad :: numeric( ) ] ;
42
+ let mut memo = Memo :: new ( ) ;
43
+
44
+ pads. extend ( repeat ( Pad :: key ( ) ) . take ( keypad_count) ) ;
30
45
31
46
input
32
47
. lines ( )
33
48
. map ( |line| {
34
- let path_len = self . path ( line, & pads) . chars ( ) . count ( ) ;
49
+ let path_len = self . path ( line, & pads, & mut memo ) . chars ( ) . count ( ) ;
35
50
let num: usize = line. trim_end_matches ( 'A' ) . parse ( ) . unwrap ( ) ;
36
51
37
52
num * path_len
38
53
} )
39
54
. sum :: < usize > ( )
40
- . to_string ( )
41
55
}
42
56
43
- fn part_two ( & self , _input : & str ) -> String {
44
- String :: from ( '0' )
45
- }
46
- }
47
-
48
- impl Day21 {
49
- fn path ( & self , code : & str , pads : & [ Pad ] ) -> String {
57
+ fn path ( & self , code : & str , pads : & [ Pad ] , memo : & mut Memo ) -> String {
50
58
if pads. is_empty ( ) {
51
59
return code. to_string ( ) ;
52
60
}
@@ -58,11 +66,20 @@ impl Day21 {
58
66
code. chars ( )
59
67
. tuple_windows ( )
60
68
. map ( |( from, to) | {
61
- self . all_shortest_paths_between_buttons ( from, to, pad)
69
+ if let Some ( path) = memo. get ( & ( from, to, pad_left. len ( ) ) ) {
70
+ return path. clone ( ) ;
71
+ }
72
+
73
+ let shortest_path = self
74
+ . all_shortest_paths_between_buttons ( from, to, pad)
62
75
. iter ( )
63
- . map ( |path| self . path ( path, pad_left) )
76
+ . map ( |path| self . path ( path, pad_left, memo ) )
64
77
. min_by_key ( |path| path. chars ( ) . count ( ) )
65
- . unwrap ( )
78
+ . unwrap ( ) ;
79
+
80
+ memo. insert ( ( from, to, pad_left. len ( ) ) , shortest_path. clone ( ) ) ;
81
+
82
+ shortest_path
66
83
} )
67
84
. collect ( )
68
85
}
@@ -121,6 +138,7 @@ impl Display for Key {
121
138
}
122
139
}
123
140
141
+ #[ derive( Clone ) ]
124
142
struct Pad {
125
143
positions : Positions ,
126
144
adjacent : Adjacent ,
@@ -182,7 +200,7 @@ impl Pad {
182
200
183
201
#[ cfg( test) ]
184
202
mod tests {
185
- use crate :: solutions:: year2024:: day21:: { Day21 , Pad } ;
203
+ use crate :: solutions:: year2024:: day21:: { Day21 , Memo , Pad } ;
186
204
use crate :: solutions:: Solution ;
187
205
188
206
const EXAMPLE : & str = r#"029A
@@ -199,12 +217,13 @@ mod tests {
199
217
#[ test]
200
218
fn path_len ( ) {
201
219
let pads = vec ! [ Pad :: numeric( ) , Pad :: key( ) , Pad :: key( ) ] ;
202
-
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( ) ) ;
220
+ let mut memo = Memo :: new ( ) ;
221
+
222
+ assert_eq ! ( 68 , Day21 . path( "029A" , & pads, & mut memo) . len( ) ) ;
223
+ assert_eq ! ( 60 , Day21 . path( "980A" , & pads, & mut memo) . len( ) ) ;
224
+ assert_eq ! ( 68 , Day21 . path( "179A" , & pads, & mut memo) . len( ) ) ;
225
+ assert_eq ! ( 64 , Day21 . path( "456A" , & pads, & mut memo) . len( ) ) ;
226
+ assert_eq ! ( 64 , Day21 . path( "379A" , & pads, & mut memo) . len( ) ) ;
227
+ assert_eq ! ( 78 , Day21 . path( "739A" , & pads, & mut memo) . len( ) ) ;
209
228
}
210
229
}
0 commit comments