Day 9 part 2, now works on final input data.
This commit is contained in:
parent
5000517fd0
commit
4e647d1bff
@ -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;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user