diff --git a/src/day4.rs b/src/day4.rs index db77825..41f64f2 100644 --- a/src/day4.rs +++ b/src/day4.rs @@ -10,7 +10,7 @@ fn parse(input: &str) -> Grid { fn part1(input: &Grid) -> u64 { (0..input.height() * input.width()) .filter(|i| *input.get(&input.coord(*i as i64).unwrap()).unwrap() == b'@') - .map(|i| input.neighbours_count(&input.coord(i as i64).unwrap(), |c| *c == b'@')) + .map(|i| input.adjacent_count(&input.coord(i as i64).unwrap(), |c| *c == b'@')) .filter(|n| *n < 4) .count() as u64 } @@ -24,7 +24,7 @@ fn part2(input: &Grid) -> u64 { for i in 0..grid.width() * grid.height() { let pos = grid.coord(i as i64).unwrap(); if grid.get(&pos).is_some_and(|c| *c == b'@') - && grid.neighbours_count(&pos, |c| *c == b'@') < 4 + && grid.adjacent_count(&pos, |c| *c == b'@') < 4 { // remove the roll grid.set(&pos, b'.'); diff --git a/utils/grid/lib.rs b/utils/grid/lib.rs index 936e2b1..daed417 100644 --- a/utils/grid/lib.rs +++ b/utils/grid/lib.rs @@ -8,7 +8,7 @@ use std::{ }; /// NW, N, NE, W, E, SW, S, SE -const ADJACENT_OFFSETS: [&(i64, i64); 8] = [ +pub const ADJACENT_OFFSETS: [&(i64, i64); 8] = [ &(-1, -1), &(0, -1), &(1, -1), @@ -20,14 +20,20 @@ const ADJACENT_OFFSETS: [&(i64, i64); 8] = [ ]; /// NESW -const CARDINAL_OFFSETS: [&(i64, i64); 4] = [&(0, -1), &(-1, 0), &(1, 0), &(0, 1)]; +pub const CARDINAL_OFFSETS: [&(i64, i64); 4] = [&(0, -1), &(-1, 0), &(1, 0), &(0, 1)]; -#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)] pub struct Coord2d { pub x: i64, pub y: i64, } +impl Debug for Coord2d { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.write_fmt(format_args!("({}, {})", self.x, self.y)) + } +} + pub trait AsCoord2d { fn to_coord(self) -> Coord2d; fn x(&self) -> i64; @@ -402,7 +408,7 @@ impl Grid { ) } /// Get all of the coordinates having value `needle` - pub fn find_all<'a>(&'a self, needle: &'a T) -> impl Iterator + 'a { + pub fn find_all<'a>(&'a self, needle: &'a T) -> impl DoubleEndedIterator + 'a { self.data .iter() .enumerate() @@ -430,19 +436,23 @@ impl Grid { } /// Return the count of neighbours (8 directions) matching predicate p - pub fn neighbours_count(&self, c: &C, mut p: P) -> usize + pub fn adjacent_count(&self, c: &C, mut p: P) -> usize where P: FnMut(&T) -> bool, { - ADJACENT_OFFSETS - .iter() - .map(|d| c.to_coord() + *d) - .filter(|c| self.get(c).is_some_and(&mut p)) - .count() + self.adjacent_iter(c).filter(|i| p(i.value)).count() + } + + /// Return the count of cardinal neighbours (4 directions) matching predicate p + pub fn cardinal_count(&self, c: &C, mut p: P) -> usize + where + P: FnMut(&T) -> bool, + { + self.cardinal_iter(c).filter(|i| p(i.value)).count() } /// Return an iterator over the 8 neighbours of c. The iterator skips neighbouring positions outside of the grid. - pub fn neighbours_iter(&self, c: &C) -> OffsetsIter { + pub fn adjacent_iter(&self, c: &C) -> OffsetsIter { OffsetsIter { grid: self, origin: c.to_coord(), @@ -636,7 +646,7 @@ FBCG"; fn neighbours_iter() { let grid = unchecked_load(); assert_eq!( - grid.neighbours_iter(&(0, 1)).collect::>(), + grid.adjacent_iter(&(0, 1)).collect::>(), [ Item { pos: Coord2d { x: 0, y: 0 },