From 2aefc33bc221190463d926ca97b284bffc9eb72d Mon Sep 17 00:00:00 2001 From: Jeremy Kaplan Date: Tue, 13 Dec 2022 22:46:43 -0800 Subject: [PATCH] =?UTF-8?q?Fix=20mutually-correcting=20bugs=20=F0=9F=98=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- 2022/src/bin/day14.rs | 66 ++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 39 deletions(-) diff --git a/2022/src/bin/day14.rs b/2022/src/bin/day14.rs index 097a084..b668307 100644 --- a/2022/src/bin/day14.rs +++ b/2022/src/bin/day14.rs @@ -3,28 +3,25 @@ use std::collections::HashSet; const INPUT: &str = include_str!("../../input/day14.txt"); fn main() { - println!("{}", part1(INPUT)); - println!("{}", part2(INPUT)); + let paths = aoc::lines(INPUT).map(Path::parse).collect(); + let wall = Wall::build(paths); + + println!("{}", part1(wall.clone())); + println!("{}", part2(wall)); } -fn part1(input: &str) -> usize { - let paths = aoc::lines(input).map(Path::parse).collect(); - let mut wall = Wall::build(paths); - +fn part1(mut wall: Wall) -> usize { while wall.add_sand_1().is_some() {} wall.render(); wall.sand.len() } -fn part2(input: &str) -> usize { - let paths = aoc::lines(input).map(Path::parse).collect(); - let mut wall = Wall::build(paths); - +fn part2(mut wall: Wall) -> usize { while let Some(_pos) = wall.add_sand_2() {} wall.render(); - wall.sand.len() + 1 // for the sand source + wall.sand.len() } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -96,6 +93,7 @@ impl Segment { } } +#[derive(Debug, Clone)] struct Wall { rocks: HashSet, sand: HashSet, @@ -120,7 +118,7 @@ impl Wall { } } - let y_floor = y_abyss; + let y_floor = y_abyss + 2; Self { rocks, @@ -178,7 +176,10 @@ impl Point { impl Wall { fn filled(&self, p: &Point) -> bool { - p == &Wall::SAND_SOURCE || self.rocks.contains(p) || self.sand.contains(p) + p == &Wall::SAND_SOURCE + || self.rocks.contains(p) + || self.sand.contains(p) + || p.y >= self.y_floor } fn empty(&self, p: &Point) -> bool { @@ -186,25 +187,7 @@ impl Wall { } fn add_sand_1(&mut self) -> Option { - let mut pos = Wall::SAND_SOURCE; - - 'tick: while pos.y <= self.y_abyss { - let candidates = vec![ - pos.mv(0, 1), // down - pos.mv(-1, 1), // down-left - pos.mv(1, 1), // down-right - ]; - - for next in candidates { - if self.empty(&next) { - pos = next; - continue 'tick; - } - } - - // Stuck! - break 'tick; - } + let pos = self.drop_sand(self.y_abyss); if pos.y < self.y_abyss { self.sand.insert(pos); @@ -215,9 +198,19 @@ impl Wall { } fn add_sand_2(&mut self) -> Option { + let pos = self.drop_sand(self.y_floor); + + if self.sand.insert(pos) { + Some(pos) + } else { + None + } + } + + fn drop_sand(&self, y_max: i32) -> Point { let mut pos = Wall::SAND_SOURCE; - 'tick: while pos.y <= self.y_floor { + 'tick: while pos.y <= y_max { let candidates = vec![ pos.mv(0, 1), // down pos.mv(-1, 1), // down-left @@ -235,12 +228,7 @@ impl Wall { break 'tick; } - if pos != Wall::SAND_SOURCE { - self.sand.insert(pos); - Some(pos) - } else { - None - } + pos } }