diff --git a/samples/day22.txt b/samples/day22.txt new file mode 100644 index 0000000..158a407 --- /dev/null +++ b/samples/day22.txt @@ -0,0 +1,7 @@ +1,0,1~1,2,1 +0,0,2~2,0,2 +0,2,3~2,2,3 +0,0,4~0,2,4 +2,0,5~2,2,5 +0,1,6~2,1,6 +1,1,8~1,1,9 \ No newline at end of file diff --git a/src/bin/day22.rs b/src/bin/day22.rs new file mode 100644 index 0000000..3eec963 --- /dev/null +++ b/src/bin/day22.rs @@ -0,0 +1,109 @@ +use std::collections::HashMap; + +use aoc_2023::*; + +type Output1 = usize; +type Output2 = Output1; + +type Coord2D = Vector2D; +type Coord = Vector3D; + +#[derive(Debug, Clone, Copy)] +struct Brick { + min: Coord, + max: Coord, +} + +impl Brick { + fn new(min: Coord, max: Coord) -> Self { + Self { min, max } + } +} + +struct Day22 { + bricks: Vec, + falls: Vec, +} + +impl Day22 { + fn fall(bricks: &mut [Brick]) -> usize { + let mut top = HashMap::::new(); + let mut count = 0; + + for b in bricks { + let mut fall = b.min.z(); + for x in b.min.x()..=b.max.x() { + for y in b.min.y()..=b.max.y() { + fall = fall.min(b.min.z() - top.get(&Coord2D::new(x, y)).unwrap_or(&0) - 1); + } + } + + if fall > 0 { + count += 1; + } + + b.min -= Coord::new(0, 0, fall); + b.max -= Coord::new(0, 0, fall); + + for x in b.min.x()..=b.max.x() { + for y in b.min.y()..=b.max.y() { + top.insert(Coord2D::new(x, y), b.max.z()); + } + } + } + + count + } + + fn compute(&mut self) { + if !self.falls.is_empty() { + // already been computed + return; + } + + // sort them for the solving + self.bricks.sort_by_key(|b| b.min.z()); + + Self::fall(&mut self.bricks); + self.falls = (0..self.bricks.len()) + .map(|i| Self::fall(&mut [&self.bricks[0..i], &self.bricks[i + 1..]].concat())) + .collect_vec(); + } +} + +impl Solution for Day22 { + fn new>(pathname: P) -> Self { + let lines: Vec = file_to_lines(pathname); + + let mut bricks = vec![]; + for (x0, y0, z0, x1, y1, z1) in lines.iter().map(|l| { + l.split(&[',', '~']) + .map(|c| c.parse::().unwrap()) + .collect_tuple() + .unwrap() + }) { + bricks.push(Brick::new(Coord::new(x0, y0, z0), Coord::new(x1, y1, z1))); + } + + Self { + bricks, + falls: vec![], + } + } + + fn part_1(&mut self) -> Output1 { + self.compute(); + self.falls.iter().filter(|b| **b == 0).count() + } + + fn part_2(&mut self) -> Output2 { + self.compute(); + self.falls.iter().sum::() + } +} + +fn main() -> Result<()> { + Day22::main() +} + +test_sample!(day_22, Day22, 5, 7);