@@ -68,6 +68,46 @@ impl IndicatorState {
6868 }
6969}
7070
71+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Default ) ]
72+ struct JoltState ( [ u16 ; 10 ] ) ;
73+
74+ impl FromStr for JoltState {
75+ type Err = AoCError ;
76+
77+ fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
78+ let mut tmp: Vec < u16 > = s. split ( ',' ) . map ( |s| s. parse ( ) ) . try_collect ( ) ?;
79+ match tmp. len ( ) . cmp ( & 10 ) {
80+ Ordering :: Less => {
81+ tmp. extend ( ( 0 ..( 10 - tmp. len ( ) ) ) . map ( |_| 0 ) ) ;
82+ }
83+ Ordering :: Equal => ( ) ,
84+ Ordering :: Greater => {
85+ return Err ( AoCError :: new ( format ! ( "Input string {s} is too long!" ) ) ) ;
86+ }
87+ }
88+ Ok ( Self ( tmp. into_iter ( ) . collect_array ( ) . unwrap ( ) ) )
89+ }
90+ }
91+
92+ impl Display for JoltState {
93+ fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
94+ write ! ( f, "{{{}}}" , self . 0 . iter( ) . join( "," ) )
95+ }
96+ }
97+
98+ impl JoltState {
99+ fn be_pushed ( mut self , button : & Button ) -> Self {
100+ for btn in button. 0 . iter ( ) . copied ( ) {
101+ self . 0 [ btn] += 1 ;
102+ }
103+ self
104+ }
105+
106+ fn still_valid ( & self , target : & Self ) -> bool {
107+ std:: iter:: zip ( self . 0 . iter ( ) , target. 0 . iter ( ) ) . all ( |( me, them) | me <= them)
108+ }
109+ }
110+
71111#[ derive( Debug ) ]
72112struct Button ( Vec < usize > ) ;
73113
@@ -94,6 +134,7 @@ impl Display for Button {
94134#[ derive( Debug ) ]
95135struct Machine {
96136 target : IndicatorState ,
137+ jolt_target : JoltState ,
97138 buttons : Vec < Button > ,
98139}
99140
@@ -103,7 +144,7 @@ impl FromStr for Machine {
103144 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
104145 lazy_static ! {
105146 // I swear he intentionally makes these annoying to parse with regex
106- static ref RE : Regex = Regex :: new( r"^\[([#.]+)\] ((?:\([\d,]+\) ?)+) \{[\d,]+\}$" ) . unwrap( ) ;
147+ static ref RE : Regex = Regex :: new( r"^\[([#.]+)\] ((?:\([\d,]+\) ?)+) \{( [\d,]+) \}$" ) . unwrap( ) ;
107148 }
108149
109150 let matches = RE
@@ -112,6 +153,7 @@ impl FromStr for Machine {
112153
113154 Ok ( Self {
114155 target : matches[ 1 ] . parse ( ) ?,
156+ jolt_target : matches[ 3 ] . parse ( ) ?,
115157 buttons : matches[ 2 ]
116158 . split_whitespace ( )
117159 . map ( |s| s. parse ( ) )
@@ -124,20 +166,21 @@ impl Display for Machine {
124166 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
125167 write ! (
126168 f,
127- "{} {} {{???} }" ,
169+ "{} {} {}" ,
128170 self . target,
129- self . buttons. iter( ) . join( " " )
171+ self . buttons. iter( ) . join( " " ) ,
172+ self . jolt_target
130173 )
131174 }
132175}
133176
134- struct PushResult {
135- last_button : usize ,
136- state : IndicatorState ,
137- }
138-
139177impl Machine {
140178 fn part_1 ( & self ) -> usize {
179+ struct PushResult {
180+ last_button : usize ,
181+ state : IndicatorState ,
182+ }
183+
141184 let current_state: IndicatorState = Default :: default ( ) ;
142185
143186 let mut pushes: Vec < PushResult > = self
@@ -175,6 +218,53 @@ impl Machine {
175218 }
176219 unreachable ! ( ) ;
177220 }
221+
222+ fn part_2 ( & self ) -> usize {
223+ struct PushResult {
224+ last_button : usize ,
225+ state : JoltState ,
226+ }
227+
228+ let current_state: JoltState = Default :: default ( ) ;
229+
230+ let mut pushes: Vec < PushResult > = self
231+ . buttons
232+ . iter ( )
233+ . enumerate ( )
234+ . map ( |( i, btn) | PushResult {
235+ last_button : i,
236+ state : current_state. be_pushed ( btn) ,
237+ } )
238+ . collect ( ) ;
239+
240+ for i in 1 .. {
241+ if pushes
242+ . iter ( )
243+ . any ( |PushResult { state, .. } | state == & self . jolt_target )
244+ {
245+ return i;
246+ }
247+
248+ assert ! ( !pushes. is_empty( ) ) ;
249+
250+ // Let's get fucking stupid with it
251+ pushes = pushes
252+ . into_iter ( )
253+ . flat_map ( |PushResult { last_button, state } | {
254+ self . buttons
255+ . iter ( )
256+ . enumerate ( )
257+ . filter ( move |( i, _) | * i != last_button)
258+ . map ( move |( last_button, button) | PushResult {
259+ last_button,
260+ state : state. be_pushed ( button) ,
261+ } )
262+ . filter ( |push| push. state . still_valid ( & self . jolt_target ) )
263+ } )
264+ . collect ( ) ;
265+ }
266+ unreachable ! ( ) ;
267+ }
178268}
179269
180270pub fn part_1 ( data : crate :: DataIn ) -> crate :: AoCResult < String > {
@@ -189,12 +279,21 @@ pub fn part_1(data: crate::DataIn) -> crate::AoCResult<String> {
189279 Ok ( ret. to_string ( ) )
190280}
191281
282+ pub fn part_2 ( data : crate :: DataIn ) -> crate :: AoCResult < String > {
283+ let machines: Vec < Machine > = data. parse ( ) . try_collect ( ) ?;
284+ let ret: usize = machines. into_iter ( ) . map ( |machine| machine. part_2 ( ) ) . sum ( ) ;
285+ Ok ( ret. to_string ( ) )
286+ }
287+
192288inventory:: submit!( crate :: AoCDay {
193289 year: "2025" ,
194290 day: "10" ,
195291 part_1: crate :: AoCPart {
196292 main: part_1,
197293 example: part_1
198294 } ,
199- part_2: None
295+ part_2: Some ( crate :: AoCPart {
296+ main: part_2,
297+ example: part_2
298+ } )
200299} ) ;
0 commit comments