1+ use std:: hash:: { DefaultHasher , Hasher } ;
2+
13use aoc:: input_str;
24use itertools:: Itertools ;
35use nohash_hasher:: IntMap ;
46
57#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
8+ #[ repr( u8 ) ]
69enum Space {
710 Empty ,
811 Square ,
@@ -116,10 +119,12 @@ impl Reflector {
116119 for ( index, space) in self . get_col ( x) . enumerate ( ) . rev ( ) {
117120 if space. is_round ( ) {
118121 buffer[ next_location] = Space :: Round ;
119- next_location -= 1 ;
122+ // Known integer underflow at index 0. However, this is fine
123+ // because we're not going to use the value anyway.
124+ next_location = next_location. wrapping_sub ( 1 ) ;
120125 } else if space. is_square ( ) {
121126 buffer[ index] = Space :: Square ;
122- next_location = index - 1 ;
127+ next_location = index. wrapping_sub ( 1 ) ;
123128 }
124129 }
125130
@@ -156,10 +161,12 @@ impl Reflector {
156161 for ( index, space) in self . get_row ( y) . iter ( ) . enumerate ( ) . rev ( ) {
157162 if space. is_round ( ) {
158163 buffer[ next_location] = Space :: Round ;
159- next_location -= 1 ;
164+ // Known integer underflow at index 0. However, this is fine
165+ // because we're not going to use the value anyway.
166+ next_location = next_location. wrapping_sub ( 1 ) ;
160167 } else if space. is_square ( ) {
161168 buffer[ index] = Space :: Square ;
162- next_location = index - 1 ;
169+ next_location = index. wrapping_sub ( 1 ) ;
163170 }
164171 }
165172
@@ -182,21 +189,15 @@ impl Reflector {
182189 . sum ( )
183190 }
184191
185- /// Calculates the amount of load on the east beam
186- fn east_load ( & self ) -> usize {
187- ( 0 ..self . width )
188- . map ( |x| {
189- ( self . width - x)
190- * ( 0 ..self . height )
191- . filter ( |y| self . get ( x, * y) . is_round ( ) )
192- . count ( )
193- } )
194- . sum ( )
195- }
192+ fn hash ( & self ) -> u64 {
193+ let mut hasher = DefaultHasher :: new ( ) ;
196194
197- /// Uses the north and east loads as a hash
198- fn load_hash ( & self ) -> usize {
199- self . north_load ( ) * self . east_load ( )
195+ // SAFETY: `Space` is repr(u8), which should mean this is fine
196+ let bytes = unsafe {
197+ std:: slice:: from_raw_parts ( self . spaces . as_ptr ( ) as * const u8 , self . spaces . len ( ) )
198+ } ;
199+ hasher. write ( bytes) ;
200+ hasher. finish ( )
200201 }
201202}
202203
@@ -219,18 +220,18 @@ fn part2(mut reflector: Reflector) -> usize {
219220 let goal = 1_000_000_000 ;
220221
221222 let mut seen = IntMap :: default ( ) ;
222- seen. insert ( reflector. load_hash ( ) , 0 ) ;
223+ seen. insert ( reflector. hash ( ) , 0 ) ;
223224
224225 for i in 1 .. {
225226 reflector. cycle ( ) ;
226- if let Some ( & j) = seen. get ( & reflector. load_hash ( ) ) {
227+ if let Some ( & j) = seen. get ( & reflector. hash ( ) ) {
227228 let remaining = ( goal - i) % ( i - j) ;
228229 for _ in 0 ..remaining {
229230 reflector. cycle ( ) ;
230231 }
231232 break ;
232233 }
233- seen. insert ( reflector. load_hash ( ) , i) ;
234+ seen. insert ( reflector. hash ( ) , i) ;
234235 }
235236
236237 reflector. north_load ( )
0 commit comments