@@ -59,6 +59,7 @@ impl Day06 {
5959 let mut dir = 0 ;
6060 let mut visited = vec ! [ 0u8 ; self . grid. len( ) ] ;
6161 let mut obstructions = vec ! [ false ; self . grid. len( ) ] ;
62+ let mut cached_step_counts = vec ! [ [ 0 ; 4 ] ; self . grid. len( ) ] ;
6263 loop {
6364 visited[ pos. y * self . cols + pos. x ] |= 1 << dir;
6465
@@ -72,7 +73,7 @@ impl Day06 {
7273 } else {
7374 if !obstructions[ next. y * self . cols + next. x ]
7475 && visited[ next. y * self . cols + next. x ] == 0
75- && self . check_cycle ( next, pos, dir, & visited)
76+ && self . check_cycle ( next, pos, dir, & visited, & mut cached_step_counts )
7677 {
7778 obstructions[ next. y * self . cols + next. x ] = true ;
7879 }
@@ -93,6 +94,7 @@ impl Day06 {
9394 pos : Point2D < usize > ,
9495 dir : usize ,
9596 visited : & [ u8 ] ,
97+ cache : & mut [ [ isize ; 4 ] ] ,
9698 ) -> bool {
9799 let ( mut power, mut lambda) = ( 1 , 1 ) ;
98100 let ( mut tortoise_pos, mut tortoise_dir) = ( pos, dir) ;
@@ -107,17 +109,50 @@ impl Day06 {
107109 }
108110 lambda += 1 ;
109111
110- let next = hare_pos. wrapping_add_signed ( DIRECTIONS [ hare_dir] ) ;
111- if next. x >= self . cols || next. y >= self . rows {
112- // No cycle, hare has left the grid
113- return false ;
114- }
115- if self . grid [ next. y * self . cols + next. x ] == b'#' || next == obstruction {
116- hare_dir = ( hare_dir + 1 ) % 4 ;
112+ // Advance to the next obstruction
113+ if hare_pos. x == obstruction. x || hare_pos. y == obstruction. y {
114+ // On the same X or Y line as the temporary obstruction, loop without caching
115+ loop {
116+ let next = hare_pos. wrapping_add_signed ( DIRECTIONS [ hare_dir] ) ;
117+ if next. x >= self . cols || next. y >= self . rows {
118+ // No cycle, hare has left the grid
119+ return false ;
120+ }
121+ if self . grid [ next. y * self . cols + next. x ] == b'#' || next == obstruction {
122+ break ;
123+ }
124+ hare_pos = next;
125+ }
117126 } else {
118- hare_pos = next;
127+ // Temporary obstruction can be ignored as not on the same X or Y line as it
128+ let cached_count = & mut cache[ hare_pos. y * self . cols + hare_pos. x ] [ hare_dir] ;
129+ if * cached_count > 0 {
130+ // Advanced by the previously cached count
131+ hare_pos = hare_pos. wrapping_add_signed ( DIRECTIONS [ hare_dir] * * cached_count) ;
132+ if hare_pos. x >= self . cols || hare_pos. y >= self . rows {
133+ // No cycle, hare has left the grid
134+ return false ;
135+ }
136+ } else {
137+ // Loop, caching the step count until the next obstruction
138+ loop {
139+ let next = hare_pos. wrapping_add_signed ( DIRECTIONS [ hare_dir] ) ;
140+ if next. x >= self . cols || next. y >= self . rows {
141+ // No cycle, hare has left the grid
142+ * cached_count += 1 ;
143+ return false ;
144+ }
145+ if self . grid [ next. y * self . cols + next. x ] == b'#' {
146+ break ;
147+ }
148+ hare_pos = next;
149+ * cached_count += 1 ;
150+ }
151+ }
119152 }
120153
154+ hare_dir = ( hare_dir + 1 ) % 4 ;
155+
121156 if visited[ hare_pos. y * self . cols + hare_pos. x ] & ( 1 << hare_dir) != 0 {
122157 // Cycle, hare has reached a previous state from before adding the obstacle
123158 return true ;
0 commit comments