@@ -11,7 +11,6 @@ pub struct Day16 {
1111 end : usize ,
1212 offsets : [ isize ; 4 ] ,
1313 cheapest : Vec < [ u32 ; 4 ] > ,
14- turned : Vec < u8 > ,
1514 part1 : u32 ,
1615}
1716
@@ -50,7 +49,6 @@ impl Day16 {
5049
5150 let mut instance = Self {
5251 cheapest : vec ! [ [ u32 :: MAX ; 4 ] ; grid. len( ) ] ,
53- turned : vec ! [ 0 ; grid. len( ) ] ,
5452 part1 : 0 ,
5553 grid,
5654 start,
@@ -69,6 +67,7 @@ impl Day16 {
6967 fn dijkstra ( & mut self ) -> bool {
7068 let mut queue = BinaryHeap :: new ( ) ;
7169 queue. push ( Reverse ( ( 0 , self . start , 0 ) ) ) ;
70+ self . cheapest [ self . start ] [ 0 ] = 0 ;
7271
7372 while let Some ( Reverse ( ( score, index, dir) ) ) = queue. pop ( ) {
7473 if score > self . cheapest [ index] [ dir] {
@@ -92,9 +91,6 @@ impl Day16 {
9291 // Only turn if it will be the cheapest way to reach the turned state
9392 if score + 1000 < self . cheapest [ index] [ next_dir] {
9493 self . cheapest [ index] [ next_dir] = score + 1000 ;
95- // Store that this state was reached by turning, not by traversing tiles heading
96- // in the next direction to allow reversing the path correctly
97- self . turned [ index] |= 1 << next_dir;
9894
9995 if let Some ( branch) = self . find_branch (
10096 index. wrapping_add_signed ( self . offsets [ next_dir] ) ,
@@ -120,7 +116,17 @@ impl Day16 {
120116 return None ;
121117 }
122118
123- while index != self . end {
119+ loop {
120+ if score < self . cheapest [ index] [ dir] {
121+ self . cheapest [ index] [ dir] = score;
122+ } else if score > self . cheapest [ index] [ dir] {
123+ return None ;
124+ }
125+
126+ if index == self . end {
127+ break ;
128+ }
129+
124130 let mut count = 0 ;
125131 let mut next_index = 0 ;
126132 let mut next_dir = 0 ;
@@ -144,18 +150,7 @@ impl Day16 {
144150 dir = next_dir;
145151 }
146152
147- if score <= self . cheapest [ index] [ dir] {
148- self . cheapest [ index] [ dir] = score;
149- self . turned [ index] &= !( 1 << dir) ;
150- Some ( ( score, index, dir) )
151- } else if score == self . cheapest [ index] [ dir] {
152- // Ensure the new state isn't marked as only reachable by turning, which would prevent
153- // this segment from being included when reversing
154- self . turned [ index] &= !( 1 << dir) ;
155- None
156- } else {
157- None
158- }
153+ Some ( ( score, index, dir) )
159154 }
160155
161156 #[ must_use]
@@ -165,23 +160,23 @@ impl Day16 {
165160
166161 #[ must_use]
167162 pub fn part2 ( & self ) -> u32 {
168- let mut on_best = vec ! [ false ; self . grid. len( ) ] ;
169- on_best[ self . start ] = true ;
170- on_best[ self . end ] = true ;
163+ let mut on_best = vec ! [ 0u8 ; self . grid. len( ) ] ;
164+ on_best[ self . start ] = 0b1111 ;
165+ on_best[ self . end ] = 0b1111 ;
171166 for d in 0 ..4 {
172167 if self . cheapest [ self . end ] [ d] == self . part1 {
173168 let prev = self . end . wrapping_add_signed ( -self . offsets [ d] ) ;
174169 self . reverse ( prev, d, self . part1 - 1 , & mut on_best) ;
175170 }
176171 }
177- on_best. iter ( ) . filter ( |& & b| b) . count ( ) as u32
172+ on_best. iter ( ) . filter ( |& & b| b != 0 ) . count ( ) as u32
178173 }
179174
180- fn reverse ( & self , index : usize , dir : usize , score : u32 , on_best : & mut [ bool ] ) {
181- if on_best[ index] {
175+ fn reverse ( & self , index : usize , dir : usize , score : u32 , on_best : & mut [ u8 ] ) {
176+ if on_best[ index] & ( 1 << dir ) != 0 {
182177 return ;
183178 }
184- on_best[ index] = true ;
179+ on_best[ index] |= 1 << dir ;
185180
186181 let mut count = 0 ;
187182 let mut next_index = 0 ;
@@ -206,15 +201,11 @@ impl Day16 {
206201 ( ( dir + 1 ) % 4 , score - 1000 ) ,
207202 ( ( dir + 3 ) % 4 , score - 1000 ) ,
208203 ] {
204+ let next_index = index. wrapping_add_signed ( -self . offsets [ next_dir] ) ;
209205 if self . cheapest [ index] [ next_dir] == next_score
210- && self . turned [ index ] & ( 1 << next_dir) == 0
206+ && self . cheapest [ next_index ] [ next_dir] == next_score - 1
211207 {
212- self . reverse (
213- index. wrapping_add_signed ( -self . offsets [ next_dir] ) ,
214- next_dir,
215- next_score - 1 ,
216- on_best,
217- ) ;
208+ self . reverse ( next_index, next_dir, next_score - 1 , on_best) ;
218209 }
219210 }
220211 }
0 commit comments