1
1
use anyhow:: Result ;
2
+ use hashbrown:: HashMap ;
3
+ use itertools:: Itertools ;
2
4
use libaoc:: { aoc, AocResult , Timer } ;
3
- use std:: collections:: BTreeMap ;
5
+ use std:: convert:: TryInto ;
6
+
7
+ type Coords < const SIZE : usize > = [ i32 ; SIZE ] ;
8
+
9
+ fn get_neighbors < const SIZE : usize > (
10
+ location : Coords < SIZE > ,
11
+ data : & HashMap < Coords < SIZE > , bool > ,
12
+ ) -> i32 {
13
+ let offsets = [ [ -1i32 , 0 , 1 ] ; SIZE ] ;
4
14
5
- fn get_neighbors_3 ( coords : ( i32 , i32 , i32 ) , data : & BTreeMap < ( i32 , i32 , i32 ) , bool > ) -> i32 {
6
15
let mut count = 0 ;
7
- for x in ( coords. 0 - 1 ) ..=( coords. 0 + 1 ) {
8
- for y in ( coords. 1 - 1 ) ..=( coords. 1 + 1 ) {
9
- for z in ( coords. 2 - 1 ) ..=( coords. 2 + 1 ) {
10
- if ( ( x, y, z) != coords) && * data. get ( & ( x, y, z) ) . unwrap_or ( & false ) {
11
- count += 1 ;
12
- }
13
- }
16
+ for current in offsets. iter ( ) . multi_cartesian_product ( ) {
17
+ let coords: Vec < _ > = current. iter ( ) . map ( |x| * * x) . collect ( ) ;
18
+ let coords: Coords < SIZE > = coords. try_into ( ) . unwrap ( ) ;
19
+
20
+ let coords: Vec < _ > = coords. iter ( ) . zip ( & location) . map ( |( a, b) | a + b) . collect ( ) ;
21
+ let coords: Coords < SIZE > = coords. try_into ( ) . unwrap ( ) ;
22
+
23
+ if location != coords && * data. get ( & coords) . unwrap_or ( & false ) {
24
+ count += 1 ;
14
25
}
15
26
}
16
27
17
28
count
18
29
}
19
30
20
- fn get_neighbors_4 ( coords : ( i32 , i32 , i32 , i32 ) , data : & BTreeMap < ( i32 , i32 , i32 , i32 ) , bool > ) -> i32 {
21
- let mut count = 0 ;
22
- for x in ( coords. 0 - 1 ) ..=( coords. 0 + 1 ) {
23
- for y in ( coords. 1 - 1 ) ..=( coords. 1 + 1 ) {
24
- for z in ( coords. 2 - 1 ) ..=( coords. 2 + 1 ) {
25
- for w in ( coords. 3 - 1 ) ..=( coords. 3 + 1 ) {
26
- if ( ( x, y, z, w) != coords) && * data. get ( & ( x, y, z, w) ) . unwrap_or ( & false ) {
27
- count += 1 ;
28
- }
31
+ fn game < const SIZE : usize > ( mut data : HashMap < [ i32 ; SIZE ] , bool > , width : i32 , height : i32 ) -> u32 {
32
+ let mut min_pos = [ 0 ; SIZE ] ;
33
+ let mut size = [ 1 ; SIZE ] ;
34
+ size[ 0 ] = width;
35
+ size[ 1 ] = height;
36
+
37
+ let mut new = HashMap :: new ( ) ;
38
+ for _ in 0 ..6 {
39
+ for i in min_pos. iter_mut ( ) {
40
+ * i -= 1 ;
41
+ }
42
+
43
+ for i in size. iter_mut ( ) {
44
+ * i += 1 ;
45
+ }
46
+
47
+ let iterators: Vec < Vec < _ > > = min_pos
48
+ . iter ( )
49
+ . zip ( & size)
50
+ . map ( |( & a, & b) | ( a..b) . into_iter ( ) . collect ( ) )
51
+ . collect ( ) ;
52
+ for coords in iterators. iter ( ) . multi_cartesian_product ( ) {
53
+ let coords: Vec < _ > = coords. iter ( ) . map ( |x| * * x) . collect ( ) ;
54
+ let coords: Coords < SIZE > = coords. try_into ( ) . unwrap ( ) ;
55
+
56
+ let current_state = * data. get ( & coords) . unwrap_or ( & false ) ;
57
+ let neighbors = get_neighbors ( coords, & data) ;
58
+ let new_state = if current_state {
59
+ if neighbors == 2 || neighbors == 3 {
60
+ true
61
+ } else {
62
+ false
63
+ }
64
+ } else {
65
+ if neighbors == 3 {
66
+ true
67
+ } else {
68
+ false
29
69
}
30
- }
70
+ } ;
71
+
72
+ new. insert ( coords, new_state) ;
73
+ }
74
+
75
+ ( data, new) = ( new, data) ;
76
+ new. clear ( ) ;
77
+ }
78
+
79
+ let mut count = 0 ;
80
+ for & value in data. values ( ) {
81
+ if value {
82
+ count += 1 ;
31
83
}
32
84
}
33
85
@@ -51,122 +103,23 @@ pub fn solve(timer: &mut Timer, input: &str) -> Result<AocResult> {
51
103
. collect ( ) ;
52
104
timer. lap ( "Parse" ) ;
53
105
54
- let mut data_3 = BTreeMap :: new ( ) ;
55
- let mut data_4 = BTreeMap :: new ( ) ;
106
+ let mut data_3 = HashMap :: new ( ) ;
107
+ let mut data_4 = HashMap :: new ( ) ;
56
108
for ( y, row) in input. iter ( ) . enumerate ( ) {
57
109
for ( x, & item) in row. iter ( ) . enumerate ( ) {
58
- data_3. insert ( ( x as i32 , y as i32 , 0 ) , item) ;
59
- data_4. insert ( ( x as i32 , y as i32 , 0 , 0 ) , item) ;
110
+ data_3. insert ( [ x as i32 , y as i32 , 0 ] , item) ;
111
+ data_4. insert ( [ x as i32 , y as i32 , 0 , 0 ] , item) ;
60
112
}
61
113
}
62
114
timer. lap ( "Construct maps" ) ;
63
115
64
- let mut min_pos = ( 0 , 0 , 0 ) ;
65
- let mut size = ( input[ 0 ] . len ( ) as i32 , input. len ( ) as i32 , 1 ) ;
66
-
67
- for _ in 0 ..6 {
68
- let mut new = BTreeMap :: new ( ) ;
69
-
70
- min_pos. 0 -= 1 ;
71
- min_pos. 1 -= 1 ;
72
- min_pos. 2 -= 1 ;
73
-
74
- size. 0 += 1 ;
75
- size. 1 += 1 ;
76
- size. 2 += 1 ;
77
-
78
- for x in min_pos. 0 ..size. 0 {
79
- for y in min_pos. 1 ..size. 1 {
80
- for z in min_pos. 2 ..size. 2 {
81
- let coords = ( x, y, z) ;
82
- let current_state = * data_3. get ( & coords) . unwrap_or ( & false ) ;
83
- let neighbors = get_neighbors_3 ( coords, & data_3) ;
84
- let new_state = if current_state {
85
- if neighbors == 2 || neighbors == 3 {
86
- true
87
- } else {
88
- false
89
- }
90
- } else {
91
- if neighbors == 3 {
92
- true
93
- } else {
94
- false
95
- }
96
- } ;
97
-
98
- new. insert ( coords, new_state) ;
99
- }
100
- }
101
- }
102
-
103
- data_3 = new;
104
- }
105
-
106
- let mut count = 0 ;
107
- for & value in data_3. values ( ) {
108
- if value {
109
- count += 1 ;
110
- }
111
- }
112
- let part1 = count;
116
+ let width = input[ 0 ] . len ( ) as i32 ;
117
+ let height = input. len ( ) as i32 ;
113
118
119
+ let part1 = game ( data_3, width, height) ;
114
120
timer. lap ( "Part 1" ) ;
115
121
116
-
117
- let mut min_pos = ( 0 , 0 , 0 , 0 ) ;
118
- let mut size = ( input[ 0 ] . len ( ) as i32 , input. len ( ) as i32 , 1 , 1 ) ;
119
-
120
- for _ in 0 ..6 {
121
- let mut new = BTreeMap :: new ( ) ;
122
-
123
- min_pos. 0 -= 1 ;
124
- min_pos. 1 -= 1 ;
125
- min_pos. 2 -= 1 ;
126
- min_pos. 3 -= 1 ;
127
-
128
- size. 0 += 1 ;
129
- size. 1 += 1 ;
130
- size. 2 += 1 ;
131
- size. 3 += 1 ;
132
-
133
- for x in min_pos. 0 ..size. 0 {
134
- for y in min_pos. 1 ..size. 1 {
135
- for z in min_pos. 2 ..size. 2 {
136
- for w in min_pos. 3 ..size. 3 {
137
- let coords = ( x, y, z, w) ;
138
- let current_state = * data_4. get ( & coords) . unwrap_or ( & false ) ;
139
- let neighbors = get_neighbors_4 ( coords, & data_4) ;
140
- let new_state = if current_state {
141
- if neighbors == 2 || neighbors == 3 {
142
- true
143
- } else {
144
- false
145
- }
146
- } else {
147
- if neighbors == 3 {
148
- true
149
- } else {
150
- false
151
- }
152
- } ;
153
-
154
- new. insert ( coords, new_state) ;
155
- }
156
- }
157
- }
158
- }
159
-
160
- data_4 = new;
161
- }
162
-
163
- let mut count = 0 ;
164
- for & value in data_4. values ( ) {
165
- if value {
166
- count += 1 ;
167
- }
168
- }
169
- let part2 = count;
122
+ let part2 = game ( data_4, width, height) ;
170
123
timer. lap ( "Part 2" ) ;
171
124
172
125
Ok ( AocResult :: new ( part1, part2) )
0 commit comments