Watch
1
0
Fork
You've already forked advent-of-code
0

2022 Day 14: Part 2

This commit is contained in:
Jeremy Kaplan 2022-12-13 22:20:22 -08:00
commit f74bf1cab8

View file

@ -4,18 +4,29 @@ const INPUT: &str = include_str!("../../input/day14.txt");
fn main() { fn main() {
println!("{}", part1(INPUT)); println!("{}", part1(INPUT));
println!("{}", part2(INPUT));
} }
fn part1(input: &str) -> usize { fn part1(input: &str) -> usize {
let paths = aoc::lines(input).map(Path::parse).collect(); let paths = aoc::lines(input).map(Path::parse).collect();
let mut wall = Wall::build(paths); let mut wall = Wall::build(paths);
while wall.add_sand().is_some() {} while wall.add_sand_1().is_some() {}
wall.render(); wall.render();
wall.sand.len() wall.sand.len()
} }
fn part2(input: &str) -> usize {
let paths = aoc::lines(input).map(Path::parse).collect();
let mut wall = Wall::build(paths);
while let Some(_pos) = wall.add_sand_2() {}
wall.render();
wall.sand.len() + 1 // for the sand source
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
struct Point { struct Point {
x: i32, x: i32,
@ -89,6 +100,7 @@ struct Wall {
rocks: HashSet<Point>, rocks: HashSet<Point>,
sand: HashSet<Point>, sand: HashSet<Point>,
y_abyss: i32, y_abyss: i32,
y_floor: i32,
} }
impl Wall { impl Wall {
@ -108,15 +120,18 @@ impl Wall {
} }
} }
let y_floor = y_abyss;
Self { Self {
rocks, rocks,
sand, sand,
y_abyss, y_abyss,
y_floor,
} }
} }
fn render(&self) { fn render(&self) {
let (lo, hi) = self.rocks.iter().fold( let (lo, hi) = self.rocks.iter().chain(self.sand.iter()).fold(
(Wall::SAND_SOURCE, Wall::SAND_SOURCE), (Wall::SAND_SOURCE, Wall::SAND_SOURCE),
|(lo, hi), Point { x, y }| { |(lo, hi), Point { x, y }| {
( (
@ -170,7 +185,7 @@ impl Wall {
!self.filled(p) !self.filled(p)
} }
fn add_sand(&mut self) -> Option<Point> { fn add_sand_1(&mut self) -> Option<Point> {
let mut pos = Wall::SAND_SOURCE; let mut pos = Wall::SAND_SOURCE;
'tick: while pos.y <= self.y_abyss { 'tick: while pos.y <= self.y_abyss {
@ -198,6 +213,35 @@ impl Wall {
None None
} }
} }
fn add_sand_2(&mut self) -> Option<Point> {
let mut pos = Wall::SAND_SOURCE;
'tick: while pos.y <= self.y_floor {
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;
}
if pos != Wall::SAND_SOURCE {
self.sand.insert(pos);
Some(pos)
} else {
None
}
}
} }
fn minmax<T: PartialOrd>(a: T, b: T) -> (T, T) { fn minmax<T: PartialOrd>(a: T, b: T) -> (T, T) {