From 8ccab04d6fa45f7ca6a2ac8f2356134911523b3a Mon Sep 17 00:00:00 2001 From: kageru Date: Sat, 11 Dec 2021 22:54:57 +0100 Subject: [PATCH] Extract some grid functionality into trait --- 2021/src/bin/day09.rs | 2 +- 2021/src/bin/day11.rs | 8 ++++---- 2021/src/grid.rs | 39 ++++++++++++++++++++++++--------------- 2021/src/grid/position.rs | 1 + 4 files changed, 30 insertions(+), 20 deletions(-) diff --git a/2021/src/bin/day09.rs b/2021/src/bin/day09.rs index 49659ac..1799c6e 100644 --- a/2021/src/bin/day09.rs +++ b/2021/src/bin/day09.rs @@ -4,7 +4,7 @@ use std::collections::HashSet; use aoc2021::common::*; -const DAY: usize = 09; +const DAY: usize = 9; type Parsed = Vec>; fn parse_input(raw: &str) -> Parsed { diff --git a/2021/src/bin/day11.rs b/2021/src/bin/day11.rs index e162d99..9e98abe 100644 --- a/2021/src/bin/day11.rs +++ b/2021/src/bin/day11.rs @@ -3,15 +3,15 @@ extern crate test; use aoc2021::{ common::*, - grid::{Grid, PositionND}, + grid::{Grid, HashGrid, PositionND}, }; const DAY: usize = 11; const ROUNDS: usize = 100; -type Parsed = Grid; +type Parsed = HashGrid; fn parse_input(raw: &str) -> Parsed { - Grid::::from_bytes_2d(raw, |b: u8| b - b'0') + HashGrid::::from_bytes_2d(raw, |b: u8| b - b'0') } fn part1(parsed: &Parsed) -> usize { @@ -80,5 +80,5 @@ mod tests { test!(part2() == 195); bench!(part1() == 1741); bench!(part2() == 440); - bench_input!(Grid::len => 100); + bench_input!(HashGrid::len => 100); } diff --git a/2021/src/grid.rs b/2021/src/grid.rs index 5aa4d3b..5f6b843 100644 --- a/2021/src/grid.rs +++ b/2021/src/grid.rs @@ -2,40 +2,50 @@ pub mod cell; pub mod direction; pub mod position; pub use direction::*; -pub use position::*; - use itertools::join; +pub use position::*; use std::{collections::HashMap, fmt::Display, hash::BuildHasher}; +#[allow(clippy::len_without_is_empty)] // I mainly have this for assertions in benchmarks +pub trait Grid { + fn get(&self, pos: &PositionND) -> Option<&T>; + + fn insert>>(&mut self, pos: Pos, element: T); + + fn len(&self) -> usize; +} + #[derive(Debug, Clone, PartialEq)] -pub struct Grid { +pub struct HashGrid { pub fields: HashMap, T>, } -impl Grid { - pub fn get(&self, pos: &PositionND) -> T { - self.fields.get(pos).copied().unwrap_or_else(T::default) +impl Grid for HashGrid { + fn get(&self, pos: &PositionND) -> Option<&T> { + self.fields.get(pos) } - pub fn insert>>(&mut self, pos: Pos, t: T) { + fn insert>>(&mut self, pos: Pos, t: T) { self.fields.insert(pos.into(), t); } - pub fn from_bytes_2d T + Copy>(raw: &str, mut f: F) -> Grid { + fn len(&self) -> usize { + self.fields.len() + } +} + +impl HashGrid { + pub fn from_bytes_2d T + Copy>(raw: &str, mut f: F) -> HashGrid { raw.lines() .enumerate() .flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, c)| (PositionND { points: [x as i64, y as i64] }, f(c)))) .collect() } - - pub fn len(&self) -> usize { - self.fields.len() - } } -impl std::iter::FromIterator<(PositionND, T)> for Grid { +impl std::iter::FromIterator<(PositionND, T)> for HashGrid { fn from_iter, T)>>(iter: I) -> Self { - Grid { fields: iter.into_iter().collect() } + HashGrid { fields: iter.into_iter().collect() } } } @@ -46,7 +56,6 @@ struct Boundaries { y_max: i64, } -#[rustfmt::skip] fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries { let x_min = input.iter().min_by_key(|k| k.points[0]).map(|p| p.points[0]).unwrap_or(0); let x_max = input.iter().max_by_key(|k| k.points[0]).map(|p| p.points[0]).unwrap_or(0); diff --git a/2021/src/grid/position.rs b/2021/src/grid/position.rs index 2fe8dde..b959d7e 100644 --- a/2021/src/grid/position.rs +++ b/2021/src/grid/position.rs @@ -49,6 +49,7 @@ impl PositionND { pub fn from_padded(slice: &[i64]) -> PositionND { let mut points = [0; DIMS]; + #[allow(clippy::manual_memcpy)] for i in 0..(DIMS.min(slice.len())) { points[i] = slice[i]; }