1111//! The cursor also doesn't move too far, only covering a range of about 6,000 steps.
1212use crate :: util:: hash:: * ;
1313use crate :: util:: parse:: * ;
14+ use std:: iter:: repeat_with;
1415
1516pub struct Input {
1617 state : usize ,
@@ -20,13 +21,13 @@ pub struct Input {
2021
2122struct Rule {
2223 next_state : usize ,
23- next_tape : usize ,
24+ next_tape : bool ,
2425 advance : bool ,
2526}
2627
2728impl Rule {
2829 fn parse ( block : & [ & [ u8 ] ] ) -> Self {
29- let next_tape = ( block[ 0 ] [ 22 ] - b'0' ) as usize ;
30+ let next_tape = block[ 0 ] [ 22 ] == b'1' ;
3031 let advance = block[ 1 ] [ 27 ] == b'r' ;
3132 let next_state = ( block[ 2 ] [ 26 ] - b'A' ) as usize ;
3233 Rule { next_state, next_tape, advance }
@@ -60,18 +61,18 @@ pub fn part1(input: &Input) -> u32 {
6061 let mut tape = 0 ;
6162 let mut left = Vec :: new ( ) ;
6263 let mut right = Vec :: new ( ) ;
63- let mut cache = FastMap :: new ( ) ;
64+ let mut cache: Vec < _ > = repeat_with ( FastMap :: new) . take ( input . rules . len ( ) ) . collect ( ) ;
6465
6566 loop {
6667 // Lookup the next batch state transition.
67- let Skip { next_state, next_tape, steps, advance } = * cache
68- . entry ( ( state , tape) )
68+ let Skip { next_state, next_tape, steps, advance } = * cache[ state ]
69+ . entry ( tape)
6970 . or_insert_with ( || turing ( & input. rules , state, tape, u32:: MAX ) ) ;
7071
7172 // Handle any remaining transitions less than the batch size one step at a time.
7273 if steps > remaining {
7374 let Skip { next_tape, .. } = turing ( & input. rules , state, tape, remaining) ;
74- tape = next_tape;
75+ left . push ( next_tape) ;
7576 break ;
7677 }
7778
@@ -91,9 +92,7 @@ pub fn part1(input: &Input) -> u32 {
9192 }
9293 }
9394
94- tape. count_ones ( )
95- + left. iter ( ) . map ( |& n| n. count_ones ( ) ) . sum :: < u32 > ( )
96- + right. iter ( ) . map ( |& n| n. count_ones ( ) ) . sum :: < u32 > ( )
95+ left. into_iter ( ) . chain ( right) . map ( u128:: count_ones) . sum ( )
9796}
9897
9998pub fn part2 ( _input : & Input ) -> & ' static str {
@@ -111,7 +110,7 @@ fn turing(rules: &[[Rule; 2]], mut state: usize, mut tape: u128, max_steps: u32)
111110 let current = usize:: from ( tape & mask != 0 ) ;
112111 let Rule { next_state, next_tape, advance } = rules[ state] [ current] ;
113112
114- if next_tape == 1 {
113+ if next_tape {
115114 tape |= mask;
116115 } else {
117116 tape &= !mask;
0 commit comments