@@ -37,25 +37,23 @@ pub fn parse(input: &str) -> FastSet<Hex> {
37
37
b'e' => q += 1 ,
38
38
b'w' => q -= 1 ,
39
39
b'n' => {
40
- if b'e' == iter. next ( ) . unwrap ( ) {
40
+ r -= 1 ;
41
+ if iter. next ( ) . unwrap ( ) == b'e' {
41
42
q += 1 ;
42
43
}
43
- r -= 1 ;
44
44
}
45
45
b's' => {
46
- if b'e' != iter. next ( ) . unwrap ( ) {
46
+ r += 1 ;
47
+ if iter. next ( ) . unwrap ( ) == b'w' {
47
48
q -= 1 ;
48
49
}
49
- r += 1 ;
50
50
}
51
51
_ => unreachable ! ( ) ,
52
52
}
53
53
}
54
54
55
55
let tile = Hex { q, r } ;
56
- if tiles. contains ( & tile) {
57
- tiles. remove ( & tile) ;
58
- } else {
56
+ if !tiles. remove ( & tile) {
59
57
tiles. insert ( tile) ;
60
58
}
61
59
}
@@ -80,7 +78,6 @@ pub fn part2(input: &FastSet<Hex>) -> usize {
80
78
#[ cfg( not( feature = "simd" ) ) ]
81
79
mod scalar {
82
80
use super :: * ;
83
- use std:: array:: from_fn;
84
81
85
82
pub ( super ) fn simulate ( input : & FastSet < Hex > ) -> usize {
86
83
// Determine bounds
@@ -91,30 +88,32 @@ mod scalar {
91
88
92
89
// Create array with enough space to allow expansion for 100 generations.
93
90
// 2 * (100 generations + 1 buffer) + Origin = 203 extra in each dimension
94
- let width = q2 - q1 + 203 ;
95
- let height = r2 - r1 + 203 ;
96
- let neighbors: [ i32 ; 6 ] = [ -1 , 1 , -width, width, 1 - width, width - 1 ] ;
97
- let neighbors: [ usize ; 6 ] = from_fn ( |i| neighbors[ i] as usize ) ;
91
+ let width = ( q2 - q1 + 203 ) as usize ;
92
+ let height = ( r2 - r1 + 203 ) as usize ;
98
93
94
+ let mut state = vec ! [ 0_u8 ; width * height] ;
99
95
let mut active = Vec :: with_capacity ( 5_000 ) ;
100
96
let mut candidates = Vec :: with_capacity ( 5_000 ) ;
101
97
let mut next_active = Vec :: with_capacity ( 5_000 ) ;
102
98
103
99
// Create initial active state, offsetting tiles so that all indices are positive.
104
100
for hex in input {
105
- let index = width * ( hex. r - r1 + 101 ) + ( hex. q - q1 + 101 ) ;
106
- active. push ( index as usize ) ;
101
+ let index = width * ( hex. r - r1 + 101 ) as usize + ( hex. q - q1 + 101 ) as usize ;
102
+ active. push ( index) ;
107
103
}
108
104
109
105
for _ in 0 ..100 {
110
- let mut state: Vec < u8 > = vec ! [ 0 ; ( width * height ) as usize ] ;
106
+ state. fill ( 0 ) ;
111
107
112
108
for & tile in & active {
113
- for & offset in & neighbors {
114
- // Earlier we converted the offsets from signed `i32` to unsigned `usize`. To
115
- // achieve subtraction for negative indices, we use a `wrapping_add` that performs
116
- // [two's complement](https://en.wikipedia.org/wiki/Two%27s_complement) arithmetic.
117
- let index = tile. wrapping_add ( offset) ;
109
+ for index in [
110
+ tile + 1 ,
111
+ tile - 1 ,
112
+ tile + width,
113
+ tile - width,
114
+ tile + 1 - width,
115
+ tile - 1 + width,
116
+ ] {
118
117
state[ index] += 1 ;
119
118
120
119
if state[ index] == 2 {
@@ -177,9 +176,9 @@ mod simd {
177
176
current[ index] = 1 ;
178
177
}
179
178
180
- let zero: Vector = Simd :: splat ( 0 ) ;
181
- let one: Vector = Simd :: splat ( 1 ) ;
182
- let two: Vector = Simd :: splat ( 2 ) ;
179
+ let zero = Simd :: splat ( 0 ) ;
180
+ let one = Simd :: splat ( 1 ) ;
181
+ let two = Simd :: splat ( 2 ) ;
183
182
184
183
for round in 0 ..100 {
185
184
// The active state boundary expands by 1 horizontally and vertically each round.
0 commit comments