@@ -47,6 +47,24 @@ impl Dir {
4747 Dir :: W => i. wrapping_sub ( 2 ) ,
4848 }
4949 }
50+
51+ fn select_crosline ( & self , i : usize ) -> u8 {
52+ ( match self {
53+ Dir :: N => i / SIZE1 ,
54+ Dir :: E => i % SIZE1 ,
55+ Dir :: S => i / SIZE1 ,
56+ Dir :: W => i % SIZE1 ,
57+ } ) as u8
58+ }
59+
60+ fn select_inline ( & self , i : usize ) -> u8 {
61+ ( match self {
62+ Dir :: N => i % SIZE1 ,
63+ Dir :: E => i / SIZE1 ,
64+ Dir :: S => i % SIZE1 ,
65+ Dir :: W => i / SIZE1 ,
66+ } ) as u8
67+ }
5068}
5169
5270#[ aoc( day20, part1) ]
@@ -121,82 +139,110 @@ pub fn part2(s: &str) -> u64 {
121139 }
122140}
123141
142+ #[ derive( Debug ) ]
143+ struct Line {
144+ start_ns : u16 ,
145+ line_start : u8 ,
146+ lien_offset : u8 ,
147+ }
148+
149+ const QUAD_SIZE : usize = 8 ;
150+ const QUADS_SIZE : usize = SIZE . div_ceil ( QUAD_SIZE ) ;
151+ const QUADS_NEEDED : usize = 20usize . div_ceil ( QUAD_SIZE ) ;
152+
124153// #[target_feature(enable = "avx2,bmi1,bmi2,cmpxchg16b,lzcnt,movbe,popcnt")]
125154fn inner_part2 ( s : & [ u8 ] ) -> u64 {
126155 let start = memchr:: memchr ( b'S' , s) . unwrap ( ) ;
127156
128- let mut ns_map = [ 0u16 ; SIZE1 * SIZE ] ;
157+ let mut lines = [ const { heapless:: Vec :: < Line , 512 > :: new ( ) } ; 4 ] ;
158+ let mut quads =
159+ [ const { [ const { heapless:: Vec :: < usize , 8 > :: new ( ) } ; QUADS_SIZE * QUADS_SIZE ] } ; 4 ] ;
129160
130161 let mut ns = 1 ;
131162
132- let mut d = if s[ start - 1 ] == b'.' {
163+ let mut i = start;
164+ let mut d = if s[ i - 1 ] == b'.' {
133165 Dir :: W
134- } else if s[ start + 1 ] == b'.' {
166+ } else if s[ i + 1 ] == b'.' {
135167 Dir :: E
136- } else if s[ start - SIZE1 ] == b'.' {
168+ } else if s[ i - SIZE1 ] == b'.' {
137169 Dir :: N
138170 } else {
139171 Dir :: S
140172 } ;
141173
142- let mut cy = start as i32 / SIZE1 as i32 ;
143- let mut cx = start as i32 % SIZE1 as i32 ;
144-
145- let idx = |x, y| ( y * SIZE1 as i32 + x) as usize ;
174+ lines[ d as usize ]
175+ . push ( Line {
176+ start_ns : 0 ,
177+ line_start : d. select_crosline ( i) ,
178+ lien_offset : d. select_inline ( i) ,
179+ } )
180+ . unwrap ( ) ;
146181
147182 let mut sum = 0 ;
148- while s[ idx ( cx, cy) ] != b'E' {
149- ns_map[ idx ( cx, cy) ] = ns;
150183
151- let next = d. step ( idx ( cx, cy) ) ;
152- if s[ next] == b'#' {
153- for side in d. sides ( ) {
154- let side_i = side. step ( idx ( cx, cy) ) ;
155- if s[ side_i] != b'#' {
156- d = side;
184+ let mut prev_qx = usize:: MAX ;
185+ let mut prev_qy = usize:: MAX ;
186+ while s[ i] != b'E' {
187+ let qx = ( i % SIZE1 ) / QUAD_SIZE ;
188+ let qy = ( i / SIZE1 ) / QUAD_SIZE ;
189+
190+ for qx in
191+ qx. saturating_sub ( QUADS_NEEDED ) ..qx. saturating_add ( QUADS_NEEDED + 1 ) . min ( QUADS_SIZE )
192+ {
193+ for qy in
194+ qy. saturating_sub ( QUADS_NEEDED ) ..qy. saturating_add ( QUADS_NEEDED + 1 ) . min ( QUADS_SIZE )
195+ {
196+ for line_i in & quads[ 0 ] [ qy * QUADS_SIZE + qx] {
197+ sum += 1 ;
198+ }
199+ for line_i in & quads[ 1 ] [ qy * QUADS_SIZE + qx] {
200+ sum += 1 ;
201+ }
202+ for line_i in & quads[ 2 ] [ qy * QUADS_SIZE + qx] {
203+ sum += 1 ;
204+ }
205+ for line_i in & quads[ 3 ] [ qy * QUADS_SIZE + qx] {
206+ sum += 1 ;
157207 }
158208 }
159209 }
160- match d {
161- Dir :: N => cy -= 1 ,
162- Dir :: E => cx += 1 ,
163- Dir :: S => cy += 1 ,
164- Dir :: W => cx -= 1 ,
165- }
166- ns += 1 ;
167210
168- for y in ( cy - 20 ) . max ( 1 ) ..( cy + 21 ) . min ( SIZE as i32 - 1 ) {
169- for x in
170- ( -20 + ( y - cy) . abs ( ) + cx) . max ( 1 ) ..( 21 - ( y - cy) . abs ( ) + cx) . min ( SIZE as i32 - 1 )
171- {
172- let dist = ( y - cy) . abs ( ) + ( x - cx) . abs ( ) ;
173- if dist <= 1 {
174- continue ;
175- }
211+ if prev_qy != qy || prev_qx != qx {
212+ quads[ d as usize ] [ qy * QUADS_SIZE + qx]
213+ . push ( lines[ d as usize ] . len ( ) - 1 )
214+ . unwrap ( ) ;
215+ }
216+ prev_qy = qy;
217+ prev_qx = qx;
176218
177- let side_i = idx ( x , y ) ;
178- if ns_map [ side_i ] != 0 {
179- let diff = ns - ns_map [ side_i ] ;
180- if diff >= MIN_CHEAT + dist as u16 {
181- sum += 1 ;
182- }
219+ let next = d . step ( i ) ;
220+ if s [ next ] == b'#' {
221+ for side in d . sides ( ) {
222+ let side_i = side . step ( i ) ;
223+ if s [ side_i ] != b'#' {
224+ d = side ;
183225 }
184226 }
227+
228+ lines[ d as usize ]
229+ . push ( Line {
230+ start_ns : ns,
231+ line_start : d. select_crosline ( i) ,
232+ lien_offset : d. select_inline ( i) ,
233+ } )
234+ . unwrap ( ) ;
235+ quads[ d as usize ] [ qy * QUADS_SIZE + qx]
236+ . push ( lines[ d as usize ] . len ( ) - 1 )
237+ . unwrap ( ) ;
238+
239+ i = d. step ( i) ;
240+ } else {
241+ i = next;
185242 }
243+ ns += 1 ;
186244 }
187245
188- // for y in 0..SIZE {
189- // for x in 0..SIZE.min(40) {
190- // if ns_map[y * SIZE1 + x] != 0 {
191- // print!("{:^4} ", ns_map[y * SIZE1 + x]);
192- // } else {
193- // print!(" . ");
194- // }
195- // }
196- // println!("");
197- // }
198- // println!("");
199-
200246 sum
201247}
202248
0 commit comments