grid: improve ergonomics with more trait impls and other improvements

update puzzles to pass tests, some performance gains
This commit is contained in:
2024-12-12 02:14:29 -08:00
parent c213bbbc27
commit 447ff5c62c
5 changed files with 88 additions and 53 deletions

View File

@ -1,19 +1,19 @@
use aoc_runner_derive::{aoc, aoc_generator};
use grid::Grid;
use itertools::Itertools;
use std::io::{BufRead, Lines};
use std::io::BufRead;
#[aoc_generator(day10)]
pub fn get_input(input: &[u8]) -> TrailMap {
TrailMap::from(input.lines())
TrailMap::from(input)
}
pub struct TrailMap {
map: Grid<u8>,
}
impl<T: BufRead> From<Lines<T>> for TrailMap {
fn from(input: Lines<T>) -> Self {
impl<T: BufRead> From<T> for TrailMap {
fn from(input: T) -> Self {
Self { map: input.into() }
}
}
@ -29,13 +29,13 @@ impl TrailMap {
.collect_vec()
}
fn count_reachable_from(&self, pos: &(i64, i64), needle: u8, visited: &mut Grid<bool>) -> u64 {
if visited.get(pos) == Some(true) {
if visited.get(pos) == Some(&true) {
return 0;
} else {
visited.set(pos, true);
}
let our_val = self.map.get(pos).unwrap();
if our_val == needle {
if *our_val == needle {
return 1;
}
// adjacents that are +1
@ -43,7 +43,7 @@ impl TrailMap {
.iter()
.map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
.map(|target_pos| (target_pos, self.map.get(&target_pos))) // get value at that position
.filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
.filter(|(_, val)| *val == Some(&(our_val + 1))) // only interested if it's our value + 1
.map(|(pos, _)| pos) // discard the value
.map(|pos| self.count_reachable_from(&pos, needle, visited))
.sum()
@ -51,14 +51,14 @@ impl TrailMap {
fn count_paths_to(&self, pos: &(i64, i64), needle: u8) -> u64 {
let our_val = self.map.get(pos).unwrap();
if our_val == needle {
if *our_val == needle {
return 1;
}
[(-1, 0), (1, 0), (0, -1), (0, 1)] // left, right, up, down
.iter()
.map(|(x_ofs, y_ofs)| (pos.0 + x_ofs, pos.1 + y_ofs)) // get target position
.map(|target_pos| (target_pos, self.map.get(&target_pos))) // get value at that position
.filter(|(_, val)| *val == Some(our_val + 1)) // only interested if it's our value + 1
.filter(|(_, val)| *val == Some(&(our_val + 1))) // only interested if it's our value + 1
.map(|(pos, _)| pos) // discard the value
.map(|mov| self.count_paths_to(&mov, needle))
.sum::<u64>()