-
Notifications
You must be signed in to change notification settings - Fork 0
/
17.rs
93 lines (87 loc) · 2.79 KB
/
17.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
use std::collections::*;
use std::hash::Hash;
static INPUT: [&str; 8] = [
"#####...",
".#..##..",
"##.##.##",
"...####.",
"#.#...##",
".##...#.",
".#.#.###",
"#.#.#..#",
];
static NEIGHBOURS: [(i8,i8,i8,i8); 80] = [
(-1,-1,-1,-1), (-1,-1,-1, 0), (-1,-1,-1, 1),
(-1,-1, 0,-1), (-1,-1, 0, 0), (-1,-1, 0, 1),
(-1,-1, 1,-1), (-1,-1, 1, 0), (-1,-1, 1, 1),
(-1, 0,-1,-1), (-1, 0,-1, 0), (-1, 0,-1, 1),
(-1, 0, 0,-1), (-1, 0, 0, 0), (-1, 0, 0, 1),
(-1, 0, 1,-1), (-1, 0, 1, 0), (-1, 0, 1, 1),
(-1, 1,-1,-1), (-1, 1,-1, 0), (-1, 1,-1, 1),
(-1, 1, 0,-1), (-1, 1, 0, 0), (-1, 1, 0, 1),
(-1, 1, 1,-1), (-1, 1, 1, 0), (-1, 1, 1, 1),
( 0,-1,-1,-1), ( 0,-1,-1, 0), ( 0,-1,-1, 1),
( 0,-1, 0,-1), ( 0,-1, 0, 0), ( 0,-1, 0, 1),
( 0,-1, 1,-1), ( 0,-1, 1, 0), ( 0,-1, 1, 1),
( 0, 0,-1,-1), ( 0, 0,-1, 0), ( 0, 0,-1, 1),
( 0, 0, 0,-1), ( 0, 0, 0, 1),
( 0, 0, 1,-1), ( 0, 0, 1, 0), ( 0, 0, 1, 1),
( 0, 1,-1,-1), ( 0, 1,-1, 0), ( 0, 1,-1, 1),
( 0, 1, 0,-1), ( 0, 1, 0, 0), ( 0, 1, 0, 1),
( 0, 1, 1,-1), ( 0, 1, 1, 0), ( 0, 1, 1, 1),
( 1,-1,-1,-1), ( 1,-1,-1, 0), ( 1,-1,-1, 1),
( 1,-1, 0,-1), ( 1,-1, 0, 0), ( 1,-1, 0, 1),
( 1,-1, 1,-1), ( 1,-1, 1, 0), ( 1,-1, 1, 1),
( 1, 0,-1,-1), ( 1, 0,-1, 0), ( 1, 0,-1, 1),
( 1, 0, 0,-1), ( 1, 0, 0, 0), ( 1, 0, 0, 1),
( 1, 0, 1,-1), ( 1, 0, 1, 0), ( 1, 0, 1, 1),
( 1, 1,-1,-1), ( 1, 1,-1, 0), ( 1, 1,-1, 1),
( 1, 1, 0,-1), ( 1, 1, 0, 0), ( 1, 1, 0, 1),
( 1, 1, 1,-1), ( 1, 1, 1, 0), ( 1, 1, 1, 1),
];
fn simulate<Pos: Hash + Eq + Copy, F: Fn(&HashSet<Pos>) -> HashMap<Pos,usize>>(
mut active: HashSet<Pos>,
count_neighbours: F,
) -> usize {
for _ in 0..6 {
active = count_neighbours(&active).iter()
.filter(|&(pos,&n)| n == 3 || (n == 2 && active.contains(pos)))
.map(|(&pos,_)| pos)
.collect();
}
active.len()
}
fn count_neighbours_p1(active: &HashSet<(i8,i8,i8)>) -> HashMap<(i8,i8,i8), usize> {
let mut neighbours = HashMap::new();
for (x,y,z) in active {
for (_,dx,dy,dz) in &NEIGHBOURS[26..52] {
*neighbours.entry((x+dx, y+dy, z+dz)).or_insert(0) += 1;
}
}
neighbours
}
fn count_neighbours_p2(active: &HashSet<(i8,i8,i8,i8)>) -> HashMap<(i8,i8,i8,i8), usize> {
let mut neighbours = HashMap::new();
for (x,y,z,w) in active {
for (dx,dy,dz,dw) in &NEIGHBOURS {
*neighbours.entry((x+dx, y+dy, z+dz, w+dw)).or_insert(0) += 1;
}
}
neighbours
}
aoc2020::main! {
let active1 = INPUT.iter()
.enumerate()
.flat_map(|(y, row)| row.chars()
.enumerate()
.filter(|&(_,b)| b == '#')
.map(move |(x,_)| (x as i8, y as i8, 0))
)
.collect::<HashSet<_>>();
let active2 = active1.iter()
.map(|&(x,y,z)| (x,y,z,0))
.collect();
let p1 = simulate(active1, count_neighbours_p1);
let p2 = simulate(active2, count_neighbours_p2);
(p1, p2)
}