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

2022 Day 14: Part 1

This commit is contained in:
Jeremy Kaplan 2022-12-13 22:11:27 -08:00
commit 4e7c75899c

View file

@ -8,11 +8,12 @@ fn main() {
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 wall = Wall::build(paths); let mut wall = Wall::build(paths);
while wall.add_sand().is_some() {}
wall.render(); wall.render();
wall.sand.len()
wall.rocks.len()
} }
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -86,43 +87,53 @@ impl Segment {
struct Wall { struct Wall {
rocks: HashSet<Point>, rocks: HashSet<Point>,
sand: HashSet<Point>,
y_abyss: i32,
} }
impl Wall { impl Wall {
const SAND_SOURCE: Point = Point { x: 500, y: 0 };
fn build(paths: Vec<Path>) -> Self { fn build(paths: Vec<Path>) -> Self {
let sand = HashSet::new();
let mut rocks = HashSet::new(); let mut rocks = HashSet::new();
let mut y_abyss = 0i32;
for path in paths { for path in paths {
for segment in path.segments() { for segment in path.segments() {
dbg!(segment);
for point in segment.tween() { for point in segment.tween() {
rocks.insert(point); rocks.insert(point);
dbg!(point); y_abyss = y_abyss.max(point.y);
} }
} }
} }
Self { rocks } Self {
rocks,
sand,
y_abyss,
}
} }
fn render(&self) { fn render(&self) {
let lo = self let (lo, hi) = self.rocks.iter().fold(
.rocks (Wall::SAND_SOURCE, Wall::SAND_SOURCE),
.iter() |(lo, hi), Point { x, y }| {
.cloned() (
.reduce(|lo, p| Point::new(lo.x.min(p.x), lo.y.min(p.y))) Point::new(lo.x.min(*x), lo.y.min(*y)),
.unwrap(); Point::new(hi.x.max(*x), hi.y.max(*y)),
)
let hi = self },
.rocks );
.iter()
.cloned()
.reduce(|hi, p| Point::new(hi.x.max(p.x), hi.y.max(p.y)))
.unwrap();
let chr = move |x: i32, y: i32| -> char { let chr = move |x: i32, y: i32| -> char {
if self.rocks.contains(&Point { x, y }) { let p = Point { x, y };
if p == Wall::SAND_SOURCE {
'+'
} else if self.rocks.contains(&p) {
'#' '#'
} else if self.sand.contains(&p) {
'o'
} else { } else {
'.' '.'
} }
@ -141,6 +152,54 @@ impl Wall {
} }
} }
impl Point {
fn mv(&self, dx: i32, dy: i32) -> Point {
Point {
x: self.x + dx,
y: self.y + dy,
}
}
}
impl Wall {
fn filled(&self, p: &Point) -> bool {
p == &Wall::SAND_SOURCE || self.rocks.contains(p) || self.sand.contains(p)
}
fn empty(&self, p: &Point) -> bool {
!self.filled(p)
}
fn add_sand(&mut self) -> Option<Point> {
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;
}
if pos.y < self.y_abyss {
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) {
if a < b { if a < b {
(a, b) (a, b)