-
Notifications
You must be signed in to change notification settings - Fork 0
/
18.rs
111 lines (96 loc) · 2.98 KB
/
18.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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#![feature(test)]
use std::collections::VecDeque;
use itertools::Itertools;
use rustc_hash::FxHashSet;
type Input = Vec<Cube>;
#[derive(Clone, Hash, PartialEq, Eq)]
struct Cube(i16, i16, i16);
impl Cube {
fn sides(&self) -> [CubeSide; 6] {
[
CubeSide(self.clone(), Dimension::X),
CubeSide(self.clone(), Dimension::Y),
CubeSide(self.clone(), Dimension::Z),
CubeSide(Cube(self.0 - 1, self.1, self.2), Dimension::X),
CubeSide(Cube(self.0, self.1 - 1, self.2), Dimension::Y),
CubeSide(Cube(self.0, self.1, self.2 - 1), Dimension::Z),
]
}
fn neighbors(&self) -> [Self; 6] {
[
Cube(self.0 - 1, self.1, self.2),
Cube(self.0 + 1, self.1, self.2),
Cube(self.0, self.1 - 1, self.2),
Cube(self.0, self.1 + 1, self.2),
Cube(self.0, self.1, self.2 - 1),
Cube(self.0, self.1, self.2 + 1),
]
}
}
#[derive(Hash, PartialEq, Eq)]
struct CubeSide(Cube, Dimension);
#[derive(Hash, PartialEq, Eq)]
enum Dimension {
X,
Y,
Z,
}
fn setup(input: &str) -> Input {
input
.trim()
.lines()
.map(|line| {
let (x, y, z) = line
.split(',')
.map(|x| x.parse().unwrap())
.collect_tuple()
.unwrap();
Cube(x, y, z)
})
.collect()
}
fn part1(input: &Input) -> usize {
let mut sides = FxHashSet::with_capacity_and_hasher(input.len() * 6, Default::default());
for cube in input {
for side in cube.sides() {
if sides.contains(&side) {
sides.remove(&side);
} else {
sides.insert(side);
}
}
}
sides.len()
}
fn part2(input: &Input) -> usize {
let mut out = 0;
let (minx, maxx) = input.iter().map(|x| x.0).minmax().into_option().unwrap();
let (miny, maxy) = input.iter().map(|x| x.1).minmax().into_option().unwrap();
let (minz, maxz) = input.iter().map(|x| x.2).minmax().into_option().unwrap();
let n = ((maxx - minx + 3) * (maxy - miny + 3) * (maxz - minz + 3)) as _;
let cubes = input.iter().collect::<FxHashSet<_>>();
let mut queue = VecDeque::with_capacity(n);
queue.push_front(Cube(minx - 1, miny - 1, minz - 1));
let mut visited = FxHashSet::with_capacity_and_hasher(n, Default::default());
while let Some(p) = queue.pop_front() {
if visited.contains(&p) {
continue;
}
visited.insert(p.clone());
for q in p.neighbors() {
if !(minx - 1..=maxx + 1).contains(&q.0)
|| !(miny - 1..=maxy + 1).contains(&q.1)
|| !(minz - 1..=maxz + 1).contains(&q.2)
{
continue;
}
if cubes.contains(&q) {
out += 1;
} else if !visited.contains(&q) {
queue.push_back(q);
}
}
}
out
}
aoc::main!(2022, 18, ex: 1);