2022 Day 14: Part 2
This commit is contained in:
parent
4e7c75899c
commit
f74bf1cab8
1 changed files with 47 additions and 3 deletions
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue