Day 9 part 2, now works on final input data.

This commit is contained in:
Bill Thiede 2021-12-09 18:01:08 -08:00
parent 5000517fd0
commit 4e647d1bff

View File

@ -60,17 +60,15 @@
//! What do you get if you multiply together the sizes of the three largest basins? //! What do you get if you multiply together the sizes of the three largest basins?
use std::{ use std::{
collections::HashSet, collections::{HashSet, VecDeque},
convert::Infallible, convert::Infallible,
fmt::{Debug, Error, Formatter}, fmt::{Debug, Error, Formatter},
num::ParseIntError, ops::Index,
ops::{Index, IndexMut},
str::FromStr, str::FromStr,
}; };
use anyhow::Result; use anyhow::Result;
use aoc_runner_derive::{aoc, aoc_generator}; use aoc_runner_derive::{aoc, aoc_generator};
use thiserror::Error;
struct HeightMap { struct HeightMap {
width: usize, width: usize,
@ -78,6 +76,17 @@ struct HeightMap {
pixels: Vec<u8>, pixels: Vec<u8>,
} }
impl Debug for HeightMap {
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> {
for y in 0..self.height {
for x in 0..self.width {
write!(f, "{}", self[(x, y)])?;
}
writeln!(f)?;
}
Ok(())
}
}
impl HeightMap { impl HeightMap {
fn low_points(&self) -> Vec<u8> { fn low_points(&self) -> Vec<u8> {
let mut pts = Vec::new(); let mut pts = Vec::new();
@ -97,24 +106,27 @@ impl HeightMap {
pts pts
} }
// counts number of neighbors greater than height and not 9. // counts number of neighbors not 9.
fn flood_fill(&self, (x, y): (isize, isize), coords: &mut HashSet<(isize, isize)>) { fn flood_fill(&self, initial: (isize, isize), coords: &mut HashSet<(isize, isize)>) {
// Off the grid, return early. // This is an iterative implementation of what would be nice to do recursively. Rust
if x < 0 || y < 0 || x > self.width as isize - 1 || y > self.height as isize - 1 { // stack overflows on the final dataset if written recursively.
return; let mut q = VecDeque::new();
} q.push_back(initial);
while let Some((x, y)) = q.pop_front() {
// Can be negative or outside the width,height, Indeximpl will return 9.
let c = self[(x, y)] as usize;
if c == 9 {
// Don't count 9's that are neighbors and don't explore their neighbors.
continue;
}
let c = self[(x as usize, y as usize)] as usize; if coords.insert((x, y)) {
if c == 9 { q.push_back((x - 1, y));
// Don't count 9's that are neighbors, and stop search. q.push_back((x, y - 1));
return; q.push_back((x + 1, y));
q.push_back((x, y + 1));
}
} }
coords.insert((x, y));
self.flood_fill((x - 1, y), coords);
self.flood_fill((x, y - 1), coords);
self.flood_fill((x + 1, y), coords);
self.flood_fill((x, y + 1), coords);
} }
fn basins(&self) -> Vec<usize> { fn basins(&self) -> Vec<usize> {
@ -128,12 +140,9 @@ impl HeightMap {
&& (x == self.width - 1 || c < self[(x + 1, y)]) && (x == self.width - 1 || c < self[(x + 1, y)])
&& (y == self.height - 1 || c < self[(x, y + 1)]) && (y == self.height - 1 || c < self[(x, y + 1)])
{ {
if c == 0 { let mut coords = HashSet::new();
let mut coords = HashSet::new(); self.flood_fill((x as isize, y as isize), &mut coords);
self.flood_fill((x as isize, y as isize), &mut coords); bs.push(coords.len());
bs.push(coords.len());
}
//panic!("{:?}", bs);
} }
} }
} }
@ -141,6 +150,7 @@ impl HeightMap {
} }
} }
// Index implementation that panics if x or y are greater than width or height.
impl Index<(usize, usize)> for HeightMap { impl Index<(usize, usize)> for HeightMap {
type Output = u8; type Output = u8;
fn index(&self, (x, y): (usize, usize)) -> &Self::Output { fn index(&self, (x, y): (usize, usize)) -> &Self::Output {
@ -148,6 +158,17 @@ impl Index<(usize, usize)> for HeightMap {
} }
} }
// Index implementation that returns 9 for out of range requests.
impl Index<(isize, isize)> for HeightMap {
type Output = u8;
fn index(&self, (x, y): (isize, isize)) -> &Self::Output {
if x < 0 || y < 0 || x > self.width as isize - 1 || y > self.height as isize - 1 {
return &9;
}
&self.pixels[x as usize + y as usize * self.width]
}
}
impl FromStr for HeightMap { impl FromStr for HeightMap {
type Err = Infallible; type Err = Infallible;