Day 18, part 2
This commit is contained in:
parent
ff8870eb3e
commit
813c9f0612
10
src/bin/d18p2.rs
Normal file
10
src/bin/d18p2.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
use aoc22::{day18, util};
|
||||||
|
|
||||||
|
pub fn main() {
|
||||||
|
let droplet = day18::parse_droplet(&util::parse_input());
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Outer surface area: {}",
|
||||||
|
day18::outer_surface_area(&droplet)
|
||||||
|
);
|
||||||
|
}
|
137
src/day18.rs
137
src/day18.rs
@ -1,6 +1,15 @@
|
|||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
|
|
||||||
pub fn parse_droplet(input: &String) -> Vec<Vec<Vec<bool>>> {
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub enum Material {
|
||||||
|
Air,
|
||||||
|
Lava,
|
||||||
|
Steam,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_droplet(input: &String) -> Vec<Vec<Vec<Material>>> {
|
||||||
let mut cubes: Vec<(usize, usize, usize)> = Vec::new();
|
let mut cubes: Vec<(usize, usize, usize)> = Vec::new();
|
||||||
|
|
||||||
for line in input.lines() {
|
for line in input.lines() {
|
||||||
@ -19,19 +28,19 @@ pub fn parse_droplet(input: &String) -> Vec<Vec<Vec<bool>>> {
|
|||||||
let (x_min, x_max) = cubes.iter().map(|c| c.0).minmax().into_option().unwrap();
|
let (x_min, x_max) = cubes.iter().map(|c| c.0).minmax().into_option().unwrap();
|
||||||
let (y_min, y_max) = cubes.iter().map(|c| c.1).minmax().into_option().unwrap();
|
let (y_min, y_max) = cubes.iter().map(|c| c.1).minmax().into_option().unwrap();
|
||||||
let (z_min, z_max) = cubes.iter().map(|c| c.2).minmax().into_option().unwrap();
|
let (z_min, z_max) = cubes.iter().map(|c| c.2).minmax().into_option().unwrap();
|
||||||
let x_len = x_max - x_min + 1;
|
let x_len = x_max - x_min + 3;
|
||||||
let y_len = y_max - y_min + 1;
|
let y_len = y_max - y_min + 3;
|
||||||
let z_len = z_max - z_min + 1;
|
let z_len = z_max - z_min + 3;
|
||||||
|
|
||||||
let mut result = vec![vec![vec![false; z_len]; y_len]; x_len];
|
let mut result = vec![vec![vec![Material::Air; z_len]; y_len]; x_len];
|
||||||
for (x, y, z) in cubes {
|
for (x, y, z) in cubes {
|
||||||
result[x - x_min][y - y_min][z - z_min] = true;
|
result[x - x_min + 1][y - y_min + 1][z - z_min + 1] = Material::Lava;
|
||||||
}
|
}
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_area(droplet: &Vec<Vec<Vec<bool>>>) -> usize {
|
pub fn surface_area(droplet: &Vec<Vec<Vec<Material>>>) -> usize {
|
||||||
let x_len = droplet.len();
|
let x_len = droplet.len();
|
||||||
assert!(x_len > 0);
|
assert!(x_len > 0);
|
||||||
let y_len = droplet[0].len();
|
let y_len = droplet[0].len();
|
||||||
@ -100,7 +109,7 @@ enum ArgOrder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn surface_area_dir(
|
fn surface_area_dir(
|
||||||
droplet: &Vec<Vec<Vec<bool>>>,
|
droplet: &Vec<Vec<Vec<Material>>>,
|
||||||
lines: &Vec<(usize, usize, Vec<usize>)>,
|
lines: &Vec<(usize, usize, Vec<usize>)>,
|
||||||
order: ArgOrder,
|
order: ArgOrder,
|
||||||
) -> usize {
|
) -> usize {
|
||||||
@ -113,11 +122,119 @@ fn surface_area_dir(
|
|||||||
ArgOrder::XZY => droplet[*a][*c][*b],
|
ArgOrder::XZY => droplet[*a][*c][*b],
|
||||||
ArgOrder::YZX => droplet[*c][*a][*b],
|
ArgOrder::YZX => droplet[*c][*a][*b],
|
||||||
};
|
};
|
||||||
if last_empty && occupied {
|
if last_empty && matches!(occupied, Material::Lava) {
|
||||||
result += 1;
|
result += 1;
|
||||||
}
|
}
|
||||||
last_empty = !occupied;
|
last_empty = matches!(occupied, Material::Air);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn outer_surface_area(droplet: &Vec<Vec<Vec<Material>>>) -> usize {
|
||||||
|
let x_len = droplet.len();
|
||||||
|
assert!(x_len > 0);
|
||||||
|
let y_len = droplet[0].len();
|
||||||
|
assert!(y_len > 0);
|
||||||
|
let z_len = droplet[0][0].len();
|
||||||
|
assert!(z_len > 0);
|
||||||
|
|
||||||
|
let mut next = Vec::new();
|
||||||
|
|
||||||
|
// top/bottom
|
||||||
|
for x in 0..x_len {
|
||||||
|
for y in 0..y_len {
|
||||||
|
next.push((x, y, 0));
|
||||||
|
next.push((x, y, z_len - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// left/right
|
||||||
|
for x in 0..x_len {
|
||||||
|
for z in 0..z_len {
|
||||||
|
next.push((x, 0, z));
|
||||||
|
next.push((x, y_len - 1, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fore/back
|
||||||
|
for y in 0..y_len {
|
||||||
|
for z in 0..z_len {
|
||||||
|
next.push((0, y, z));
|
||||||
|
next.push((x_len - 1, y, z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut visited: HashSet<_> = next.iter().map(|c| c.clone()).collect();
|
||||||
|
let generators: [Box<dyn Fn(&Coord) -> Option<Coord>>; 6] = [
|
||||||
|
Box::new(|c| go_fore(c)),
|
||||||
|
Box::new(|c| go_back(c, x_len)),
|
||||||
|
Box::new(|c| go_left(c)),
|
||||||
|
Box::new(|c| go_right(c, y_len)),
|
||||||
|
Box::new(|c| go_up(c)),
|
||||||
|
Box::new(|c| go_down(c, z_len)),
|
||||||
|
];
|
||||||
|
|
||||||
|
let mut result = 0;
|
||||||
|
while let Some(n) = next.pop().clone() {
|
||||||
|
for gen in &generators {
|
||||||
|
if let Some(c) = gen(&n) {
|
||||||
|
let occupied = droplet[c.0][c.1][c.2];
|
||||||
|
if matches!(occupied, Material::Air) && visited.insert(c) {
|
||||||
|
next.push(c);
|
||||||
|
} else if matches!(occupied, Material::Lava) {
|
||||||
|
result += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
type Coord = (usize, usize, usize);
|
||||||
|
|
||||||
|
fn go_fore(c: &Coord) -> Option<Coord> {
|
||||||
|
if c.0 > 0 {
|
||||||
|
Some((c.0 - 1, c.1, c.2))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_back(c: &Coord, x_len: usize) -> Option<Coord> {
|
||||||
|
if c.0 < x_len - 1 {
|
||||||
|
Some((c.0 + 1, c.1, c.2))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_left(c: &Coord) -> Option<Coord> {
|
||||||
|
if c.1 > 0 {
|
||||||
|
Some((c.0, c.1 - 1, c.2))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_right(c: &Coord, y_len: usize) -> Option<Coord> {
|
||||||
|
if c.1 < y_len - 1 {
|
||||||
|
Some((c.0, c.1 + 1, c.2))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_up(c: &Coord) -> Option<Coord> {
|
||||||
|
if c.2 > 0 {
|
||||||
|
Some((c.0, c.1, c.2 - 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn go_down(c: &Coord, z_len: usize) -> Option<Coord> {
|
||||||
|
if c.2 < z_len - 1 {
|
||||||
|
Some((c.0, c.1, c.2 + 1))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user