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 }