main.rs (3041B)
1 use std::collections::{HashMap, HashSet, VecDeque};
2
3 #[derive(PartialEq, Eq, Hash, Debug, Clone, Copy)]
4 struct Pos([i32; 3]);
5
6 impl Pos {
7 fn from_str(s: &str) -> Self {
8 let tmp = s
9 .split(',')
10 .map(|x| x.parse::<i32>().unwrap())
11 .collect::<Vec<i32>>();
12 Self([tmp[0], tmp[1], tmp[2]])
13 }
14 }
15
16 fn main() {
17 let input = std::fs::read_to_string("input.txt")
18 .unwrap()
19 .trim()
20 .split('\n')
21 .map(|s| Pos::from_str(s))
22 .collect::<Vec<Pos>>();
23 // 3526
24 println!("Part 1: {}", part_1(&input));
25 // 2090
26 println!("Part 2: {}", part_2(&input));
27 }
28
29 fn part_1(input: &Vec<Pos>) -> i32 {
30 let mut filled = HashSet::new();
31 let mut empty = HashMap::new();
32 for c in input {
33 empty.remove(c);
34 filled.insert(c);
35 for axis in 0..3 {
36 for delta in [-1, 1] {
37 let neighbor = {
38 let mut tmp = c.0;
39 tmp[axis] += delta;
40 Pos(tmp)
41 };
42 if !filled.contains(&neighbor) {
43 empty.insert(neighbor, *empty.get(&neighbor).unwrap_or(&0) + 1);
44 }
45 }
46 }
47 }
48
49 empty.values().sum()
50 }
51
52 fn part_2(input: &Vec<Pos>) -> i32 {
53 let mut filled = HashSet::new();
54 let mut empty = HashMap::new();
55 for c in input {
56 empty.remove(c);
57 filled.insert(c);
58 for axis in 0..3 {
59 for delta in [-1, 1] {
60 let neighbor = {
61 let mut tmp = c.0;
62 tmp[axis] += delta;
63 Pos(tmp)
64 };
65 if !filled.contains(&neighbor) {
66 empty.insert(neighbor, *empty.get(&neighbor).unwrap_or(&0) + 1);
67 }
68 }
69 }
70 }
71 let mut reachable = HashMap::new();
72 let mut queue = VecDeque::new();
73 let starter = filled.iter().max_by_key(|p| p.0[0]).unwrap();
74 queue.push_back(Pos([starter.0[0] + 1, starter.0[1], starter.0[2]]));
75 while let Some(reached) = queue.pop_front() {
76 // only needed if pushing back to queue (BFS)
77 // if reachable.contains_key(&reached) {
78 // continue;
79 // }
80 if let Some(faces) = empty.get(&reached) {
81 reachable.insert(reached, *faces);
82 } else {
83 reachable.insert(reached, 0);
84 }
85 for axis in 0..3 {
86 for delta in [-1, 1] {
87 let neighbor = {
88 let mut tmp = reached.0;
89 tmp[axis] += delta;
90 Pos(tmp)
91 };
92 if !filled.contains(&neighbor)
93 && !reachable.contains_key(&neighbor)
94 && (empty.contains_key(&reached) || empty.contains_key(&neighbor))
95 {
96 // queue.push_back(neighbor);
97 queue.push_front(neighbor);
98 }
99 }
100 }
101 }
102 reachable.values().sum()
103 }