diff --git a/src/bin/d18p1.rs b/src/bin/d18p1.rs new file mode 100644 index 0000000..d22b02a --- /dev/null +++ b/src/bin/d18p1.rs @@ -0,0 +1,7 @@ +use aoc22::{day18, util}; + +pub fn main() { + let droplet = day18::parse_droplet(&util::parse_input()); + + println!("Surface area: {}", day18::surface_area(&droplet)); +} diff --git a/src/day18.rs b/src/day18.rs new file mode 100644 index 0000000..75bcd90 --- /dev/null +++ b/src/day18.rs @@ -0,0 +1,123 @@ +use itertools::Itertools; + +pub fn parse_droplet(input: &String) -> Vec>> { + let mut cubes: Vec<(usize, usize, usize)> = Vec::new(); + + for line in input.lines() { + if line.is_empty() { + break; + } + + let mut sp = line.split(','); + cubes.push(( + sp.next().unwrap().parse().unwrap(), + sp.next().unwrap().parse().unwrap(), + sp.next().unwrap().parse().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 (z_min, z_max) = cubes.iter().map(|c| c.2).minmax().into_option().unwrap(); + let x_len = x_max - x_min + 1; + let y_len = y_max - y_min + 1; + let z_len = z_max - z_min + 1; + + let mut result = vec![vec![vec![false; z_len]; y_len]; x_len]; + for (x, y, z) in cubes { + result[x - x_min][y - y_min][z - z_min] = true; + } + + result +} + +pub fn surface_area(droplet: &Vec>>) -> 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 up = (0..x_len) + .flat_map(|x| { + (0..y_len) + .map(move |y| (x, y, (0..z_len).collect())) + .collect_vec() + }) + .collect(); + let down = (0..x_len) + .flat_map(|x| { + (0..y_len) + .map(move |y| (x, y, (0..z_len).rev().collect())) + .collect_vec() + }) + .collect(); + let left = (0..x_len) + .flat_map(|x| { + (0..z_len) + .map(move |z| (x, z, (0..y_len).collect())) + .collect_vec() + }) + .collect(); + let right = (0..x_len) + .flat_map(|x| { + (0..z_len) + .map(move |z| (x, z, (0..y_len).rev().collect())) + .collect_vec() + }) + .collect(); + let fore = (0..y_len) + .flat_map(|y| { + (0..z_len) + .map(move |z| (y, z, (0..x_len).collect())) + .collect_vec() + }) + .collect(); + let back = (0..y_len) + .flat_map(|y| { + (0..z_len) + .map(move |z| (y, z, (0..x_len).rev().collect())) + .collect_vec() + }) + .collect(); + + let mut result = 0; + result += surface_area_dir(droplet, &up, ArgOrder::XYZ); + result += surface_area_dir(droplet, &down, ArgOrder::XYZ); + result += surface_area_dir(droplet, &left, ArgOrder::XZY); + result += surface_area_dir(droplet, &right, ArgOrder::XZY); + result += surface_area_dir(droplet, &fore, ArgOrder::YZX); + result += surface_area_dir(droplet, &back, ArgOrder::YZX); + + result +} + +enum ArgOrder { + XYZ, + XZY, + YZX, +} + +fn surface_area_dir( + droplet: &Vec>>, + lines: &Vec<(usize, usize, Vec)>, + order: ArgOrder, +) -> usize { + let mut result = 0; + for (a, b, c_range) in lines { + let mut last_empty = true; + for c in c_range { + let occupied = match order { + ArgOrder::XYZ => droplet[*a][*b][*c], + ArgOrder::XZY => droplet[*a][*c][*b], + ArgOrder::YZX => droplet[*c][*a][*b], + }; + if last_empty && occupied { + result += 1; + } + last_empty = !occupied; + } + } + result +} diff --git a/src/lib.rs b/src/lib.rs index ff93375..8ca45b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ pub mod day14; pub mod day15; pub mod day16; pub mod day17; +pub mod day18; pub mod day2; pub mod day3; pub mod day4;