@@ -272,7 +272,7 @@ pub fn part2(s: &str) -> &'static str {
272272 part2_inner ( s)
273273}
274274
275- const ZSTART : u16 = 26 * 26 * 26 ;
275+ const ZSTART : u16 = 0 ;
276276
277277#[ inline( always) ]
278278pub fn part2_inner ( s : & [ u8 ] ) -> & ' static str {
@@ -287,6 +287,7 @@ pub fn part2_inner(s: &[u8]) -> &'static str {
287287 struct Gate {
288288 out_1 : u16 ,
289289 out_2 : u16 ,
290+ id : u16 ,
290291 state : State ,
291292 }
292293
@@ -301,14 +302,20 @@ pub fn part2_inner(s: &[u8]) -> &'static str {
301302 }
302303 }
303304
304- let mut gates = [ Gate {
305- out_1 : 0 ,
306- out_2 : 0 ,
307- state : State :: Or ,
308- } ; 26 * 26 * 26 + 46 ] ;
309-
310305 let mut inputs = [ ( 0u16 , 0u16 ) ; 45 ] ;
311306
307+ let mut gates_map = heapless:: FnvIndexMap :: < u16 , u16 , 512 > :: new ( ) ;
308+
309+ let mut gates = heapless:: Vec :: < Gate , 512 > :: from_slice (
310+ & [ Gate {
311+ out_1 : 0 ,
312+ out_2 : 0 ,
313+ id : 0 ,
314+ state : State :: Or ,
315+ } ; 46 ] ,
316+ )
317+ . unwrap ( ) ;
318+
312319 let mut i = CSTART ;
313320 unsafe {
314321 while i < s. len ( ) {
@@ -322,11 +329,25 @@ pub fn part2_inner(s: &[u8]) -> &'static str {
322329 let this = if * s. get_unchecked ( i + len + 12 ) == b'z' {
323330 ( s. get_unchecked ( i + len + 13 ) - b'0' ) as u16 * 10
324331 + ( s. get_unchecked ( i + len + 14 ) - b'0' ) as u16
325- + 26 * 26 * 26
326332 } else {
327- ( s. get_unchecked ( i + len + 12 ) - b'a' ) as u16 * 26 * 26
333+ let this = ( s. get_unchecked ( i + len + 12 ) - b'a' ) as u16 * 26 * 26
328334 + ( s. get_unchecked ( i + len + 13 ) - b'a' ) as u16 * 26
329- + ( s. get_unchecked ( i + len + 14 ) - b'a' ) as u16
335+ + ( s. get_unchecked ( i + len + 14 ) - b'a' ) as u16 ;
336+
337+ match gates_map. entry ( this) {
338+ heapless:: Entry :: Occupied ( occupied_entry) => * occupied_entry. get ( ) ,
339+ heapless:: Entry :: Vacant ( vacant_entry) => {
340+ let i = gates. len ( ) as u16 ;
341+ gates. push_unchecked ( Gate {
342+ out_1 : 0 ,
343+ out_2 : 0 ,
344+ id : * vacant_entry. key ( ) ,
345+ state : State :: Or ,
346+ } ) ;
347+ vacant_entry. insert ( i) . unwrap_unchecked ( ) ;
348+ i
349+ }
350+ }
330351 } ;
331352
332353 if * s. get_unchecked ( i) == b'x' || * s. get_unchecked ( i) == b'y' {
@@ -355,6 +376,34 @@ pub fn part2_inner(s: &[u8]) -> &'static str {
355376 let from2 = ( s. get_unchecked ( i + len + 5 ) - b'a' ) as u16 * 26 * 26
356377 + ( s. get_unchecked ( i + len + 6 ) - b'a' ) as u16 * 26
357378 + ( s. get_unchecked ( i + len + 7 ) - b'a' ) as u16 ;
379+ let from1 = match gates_map. entry ( from1) {
380+ heapless:: Entry :: Occupied ( occupied_entry) => * occupied_entry. get ( ) ,
381+ heapless:: Entry :: Vacant ( vacant_entry) => {
382+ let i = gates. len ( ) as u16 ;
383+ gates. push_unchecked ( Gate {
384+ out_1 : 0 ,
385+ out_2 : 0 ,
386+ id : * vacant_entry. key ( ) ,
387+ state : State :: Or ,
388+ } ) ;
389+ vacant_entry. insert ( i) . unwrap_unchecked ( ) ;
390+ i
391+ }
392+ } ;
393+ let from2 = match gates_map. entry ( from2) {
394+ heapless:: Entry :: Occupied ( occupied_entry) => * occupied_entry. get ( ) ,
395+ heapless:: Entry :: Vacant ( vacant_entry) => {
396+ let i = gates. len ( ) as u16 ;
397+ gates. push_unchecked ( Gate {
398+ out_1 : 0 ,
399+ out_2 : 0 ,
400+ id : * vacant_entry. key ( ) ,
401+ state : State :: Or ,
402+ } ) ;
403+ vacant_entry. insert ( i) . unwrap_unchecked ( ) ;
404+ i
405+ }
406+ } ;
358407
359408 gates. get_unchecked_mut ( from1 as usize ) . add_out ( this) ;
360409 gates. get_unchecked_mut ( from2 as usize ) . add_out ( this) ;
@@ -438,15 +487,22 @@ pub fn part2_inner(s: &[u8]) -> &'static str {
438487
439488 debug_assert_eq ! ( carry, ZSTART + 45 ) ;
440489
490+ for i in to_swap. iter_mut ( ) {
491+ if * i < 46 {
492+ * i = 26 * 26 * 26 + * i;
493+ } else {
494+ * i = gates. get_unchecked ( * i as usize ) . id ;
495+ }
496+ }
441497 to_swap. sort_unstable ( ) ;
442498 debug_assert_eq ! ( to_swap. len( ) , 8 ) ;
443499
444500 static mut OUTPUT : [ u8 ; 8 * 4 - 1 ] = [ b',' ; 8 * 4 - 1 ] ;
445501 let mut j = 0 ;
446502 while j < 8 {
447503 let w = * to_swap. get_unchecked ( j) ;
448- if w >= ZSTART {
449- let w = w - ZSTART ;
504+ if w >= ( 26 * 26 * 26 ) {
505+ let w = w - ( 26 * 26 * 26 ) ;
450506 OUTPUT [ j * 4 ] = b'z' ;
451507 OUTPUT [ j * 4 + 1 ] = ( w / 10 ) as u8 + b'0' ;
452508 OUTPUT [ j * 4 + 2 ] = ( w % 10 ) as u8 + b'0' ;
0 commit comments