2022 Day 18 Part 2
This commit is contained in:
parent
6031a9f16e
commit
178e2e5011
1 changed files with 154 additions and 20 deletions
|
|
@ -1,20 +1,15 @@
|
||||||
|
use std::collections::{HashMap, VecDeque};
|
||||||
|
|
||||||
const INPUT: &str = include_str!("../../input/day18.txt");
|
const INPUT: &str = include_str!("../../input/day18.txt");
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("{}", part1(INPUT));
|
let cubes = parse(INPUT);
|
||||||
|
let open_faces = part1(cubes.clone());
|
||||||
|
println!("Part 1: {}", open_faces);
|
||||||
|
println!("Part 2: {}", part2(cubes, open_faces));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn part1(input: &str) -> usize {
|
fn part1(cubes: Vec<Cube>) -> usize {
|
||||||
let cubes: Vec<Cube> = aoc::lines(input)
|
|
||||||
.map(|line| {
|
|
||||||
let coords: Vec<&str> = line.split(',').collect();
|
|
||||||
let x = coords[0].parse().unwrap();
|
|
||||||
let y = coords[1].parse().unwrap();
|
|
||||||
let z = coords[2].parse().unwrap();
|
|
||||||
Cube::new(x, y, z)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut shared_faces = 0;
|
let mut shared_faces = 0;
|
||||||
for (c1, c2) in itertools::iproduct!(&cubes, &cubes) {
|
for (c1, c2) in itertools::iproduct!(&cubes, &cubes) {
|
||||||
if c1 == c2 {
|
if c1 == c2 {
|
||||||
|
|
@ -29,22 +24,161 @@ fn part1(input: &str) -> usize {
|
||||||
6 * cubes.len() - shared_faces
|
6 * cubes.len() - shared_faces
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
fn part2(cubes: Vec<Cube>, open_faces: usize) -> usize {
|
||||||
|
let min = cubes.iter().map(Cube::min_coord).min().unwrap();
|
||||||
|
let max = cubes.iter().map(Cube::max_coord).max().unwrap();
|
||||||
|
|
||||||
|
let mut grid: HashMap<Cube, Material> = cubes
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|c| (c, Material::Water))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let lo = Cube {
|
||||||
|
x: min - 1,
|
||||||
|
y: min - 1,
|
||||||
|
z: min - 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
let hi = Cube {
|
||||||
|
x: max + 1,
|
||||||
|
y: max + 1,
|
||||||
|
z: max + 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
grid.insert(lo, Material::Steam);
|
||||||
|
grid.insert(hi, Material::Steam);
|
||||||
|
|
||||||
|
steam(&mut grid, lo, hi);
|
||||||
|
air(&mut grid, lo, hi);
|
||||||
|
|
||||||
|
let mut insulated_faces = 0;
|
||||||
|
for (&cube, &mat) in &grid {
|
||||||
|
if mat == Material::Air {
|
||||||
|
for neighbor in cube.neighbors() {
|
||||||
|
if let Some(Material::Water) = grid.get(&neighbor) {
|
||||||
|
insulated_faces += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open_faces - insulated_faces
|
||||||
|
}
|
||||||
|
|
||||||
|
fn steam(grid: &mut HashMap<Cube, Material>, lo: Cube, hi: Cube) {
|
||||||
|
let mut queue: VecDeque<Cube> = grid
|
||||||
|
.iter()
|
||||||
|
.filter_map(|(&cube, &mat)| {
|
||||||
|
if mat == Material::Steam {
|
||||||
|
Some(cube)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
while let Some(src) = queue.pop_front() {
|
||||||
|
for dst in src.neighbors() {
|
||||||
|
if dst.out_of_bounds(lo, hi) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(_mat) = grid.get(&dst) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
let old = grid.insert(dst, Material::Steam);
|
||||||
|
assert!(old.is_none());
|
||||||
|
|
||||||
|
queue.push_back(dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn air(grid: &mut HashMap<Cube, Material>, lo: Cube, hi: Cube) {
|
||||||
|
for (x, y, z) in itertools::iproduct!(lo.x..=hi.x, lo.y..=hi.y, lo.z..=hi.z) {
|
||||||
|
let cube = Cube::new(x, y, z);
|
||||||
|
grid.entry(cube).or_insert(Material::Air);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
|
enum Material {
|
||||||
|
Water,
|
||||||
|
Steam,
|
||||||
|
Air,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &str) -> Vec<Cube> {
|
||||||
|
aoc::lines(input)
|
||||||
|
.map(|line| {
|
||||||
|
let coords: Vec<&str> = line.split(',').collect();
|
||||||
|
let x = coords[0].parse().unwrap();
|
||||||
|
let y = coords[1].parse().unwrap();
|
||||||
|
let z = coords[2].parse().unwrap();
|
||||||
|
Cube::new(x, y, z)
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||||
struct Cube {
|
struct Cube {
|
||||||
x: u32,
|
x: i32,
|
||||||
y: u32,
|
y: i32,
|
||||||
z: u32,
|
z: i32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cube {
|
impl Cube {
|
||||||
fn new(x: u32, y: u32, z: u32) -> Self {
|
fn new(x: i32, y: i32, z: i32) -> Self {
|
||||||
Self { x, y, z }
|
Self { x, y, z }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn touches(&self, other: &Self) -> bool {
|
fn touches(&self, other: &Self) -> bool {
|
||||||
let dx = (self.x as i32 - other.x as i32).abs();
|
let dx = (self.x - other.x).abs();
|
||||||
let dy = (self.y as i32 - other.y as i32).abs();
|
let dy = (self.y - other.y).abs();
|
||||||
let dz = (self.z as i32 - other.z as i32).abs();
|
let dz = (self.z - other.z).abs();
|
||||||
(dx + dy + dz) == 1
|
(dx + dy + dz) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn max_coord(&self) -> i32 {
|
||||||
|
(self.x).max(self.y).max(self.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn min_coord(&self) -> i32 {
|
||||||
|
(self.x).min(self.y).min(self.z)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn neighbors(&self) -> Vec<Self> {
|
||||||
|
let deltas = vec![
|
||||||
|
(-1, 0, 0),
|
||||||
|
(0, -1, 0),
|
||||||
|
(0, 0, -1),
|
||||||
|
(1, 0, 0),
|
||||||
|
(0, 1, 0),
|
||||||
|
(0, 0, 1),
|
||||||
|
];
|
||||||
|
|
||||||
|
deltas
|
||||||
|
.iter()
|
||||||
|
.map(|(dx, dy, dz)| Self {
|
||||||
|
x: self.x + dx,
|
||||||
|
y: self.y + dy,
|
||||||
|
z: self.z + dz,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn out_of_bounds(&self, lo: Self, hi: Self) -> bool {
|
||||||
|
vec![
|
||||||
|
self.x < lo.x,
|
||||||
|
self.y < lo.y,
|
||||||
|
self.z < lo.z,
|
||||||
|
self.x > hi.x,
|
||||||
|
self.y > hi.y,
|
||||||
|
self.z > hi.z,
|
||||||
|
]
|
||||||
|
.iter()
|
||||||
|
.any(|b| *b)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue