changes to grid module

This commit is contained in:
kageru 2022-12-12 11:56:38 +01:00
parent 93e753d902
commit 77f1559f9f
4 changed files with 70 additions and 73 deletions

View File

@ -1,4 +1,3 @@
pub mod cell;
pub mod direction; pub mod direction;
pub mod position; pub mod position;
pub use direction::*; pub use direction::*;
@ -38,7 +37,7 @@ impl<T: Default + Copy> HashGrid<T, 2> {
pub fn from_bytes_2d<F: FnMut(u8) -> T + Copy>(raw: &str, mut f: F) -> HashGrid<T, 2> { pub fn from_bytes_2d<F: FnMut(u8) -> T + Copy>(raw: &str, mut f: F) -> HashGrid<T, 2> {
raw.lines() raw.lines()
.enumerate() .enumerate()
.flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, c)| (PositionND { points: [x as i64, y as i64] }, f(c)))) .flat_map(move |(y, l)| l.bytes().enumerate().map(move |(x, c)| (PositionND([x as i64, y as i64]), f(c))))
.collect() .collect()
} }
} }
@ -56,11 +55,11 @@ pub struct VecGrid<T> {
impl<T> Grid<T, 2> for VecGrid<T> { impl<T> Grid<T, 2> for VecGrid<T> {
fn get(&self, pos: &PositionND<2>) -> Option<&T> { fn get(&self, pos: &PositionND<2>) -> Option<&T> {
self.fields.get(pos.points[0] as usize)?.get(pos.points[1] as usize) self.fields.get(pos.0[0] as usize)?.get(pos.0[1] as usize)
} }
fn insert<Pos: Into<PositionND<2>>>(&mut self, pos: Pos, element: T) { fn insert<Pos: Into<PositionND<2>>>(&mut self, pos: Pos, element: T) {
let PositionND { points: [x, y] } = pos.into(); let PositionND([x, y]) = pos.into();
self.fields[x as usize][y as usize] = element; self.fields[x as usize][y as usize] = element;
} }
@ -83,12 +82,12 @@ pub struct Boundaries {
} }
pub fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries { pub fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries {
let (x_min, x_max) = match input.iter().map(|p| p.points[0]).minmax() { let (x_min, x_max) = match input.iter().map(|p| p.0[0]).minmax() {
MinMaxResult::NoElements => (0, 0), MinMaxResult::NoElements => (0, 0),
MinMaxResult::MinMax(min, max) => (min, max), MinMaxResult::MinMax(min, max) => (min, max),
MinMaxResult::OneElement(x) => (x, x), MinMaxResult::OneElement(x) => (x, x),
}; };
let (y_min, y_max) = match input.iter().map(|p| p.points[1]).minmax() { let (y_min, y_max) = match input.iter().map(|p| p.0[1]).minmax() {
MinMaxResult::NoElements => (0, 0), MinMaxResult::NoElements => (0, 0),
MinMaxResult::MinMax(min, max) => (min, max), MinMaxResult::MinMax(min, max) => (min, max),
MinMaxResult::OneElement(x) => (x, x), MinMaxResult::OneElement(x) => (x, x),
@ -100,9 +99,7 @@ pub fn draw_ascii<T: Display + Default, S: BuildHasher>(coordinates: &HashMap<Po
let b = get_boundaries(&coordinates.keys().collect::<Vec<_>>()); let b = get_boundaries(&coordinates.keys().collect::<Vec<_>>());
join( join(
(b.y_min..=b.y_max).rev().map(|y| { (b.y_min..=b.y_max).rev().map(|y| {
(b.x_min..=b.x_max) (b.x_min..=b.x_max).map(|x| coordinates.get(&PositionND([x, y])).unwrap_or(&T::default()).to_string()).collect::<String>()
.map(|x| coordinates.get(&PositionND { points: [x, y] }).unwrap_or(&T::default()).to_string())
.collect::<String>()
}), }),
"\n", "\n",
) )
@ -114,19 +111,19 @@ mod tests {
#[test] #[test]
fn test_add() { fn test_add() {
assert_eq!(PositionND::from([0, 2]) + PositionND::from([-1, 0]), [-1, 2].into()); assert_eq!(PositionND([0, 2]) + PositionND([-1, 0]), [-1, 2].into());
assert_eq!(PositionND::from([0, -1]) + PositionND::from(Direction::Up), [0, 0].into()); assert_eq!(PositionND([0, -1]) + PositionND::from(Direction::Up), [0, 0].into());
} }
#[test] #[test]
fn test_sub() { fn test_sub() {
assert_eq!(PositionND::from([0, 2]) - PositionND::from([-1, 0]), [1, 2].into()); assert_eq!(PositionND([0, 2]) - PositionND([-1, 0]), [1, 2].into());
assert_eq!(PositionND::from([0, -1]) - PositionND::from([0, -1]), [0, 0].into()); assert_eq!(PositionND([0, -1]) - PositionND([0, -1]), [0, 0].into());
} }
#[test] #[test]
fn test_mul() { fn test_mul() {
assert_eq!(PositionND::from([0, 2]) * 5, [0, 10].into()); assert_eq!(PositionND([0, 2]) * 5, [0, 10].into());
assert_eq!(PositionND::from([0, -1]) * -2, [0, 2].into()); assert_eq!(PositionND([0, -1]) * -2, [0, 2].into());
} }
} }

View File

@ -38,7 +38,7 @@ impl_op!(+ |a: Direction, b: i8| -> Direction {
Direction::Down => Direction::Up, Direction::Down => Direction::Up,
Direction::Left => Direction::Right, Direction::Left => Direction::Right,
}, },
n => unreachable!(format!("Illegal turn value: {}", n)), n => unreachable!("Illegal turn value: {n}"),
} }
}); });

View File

@ -7,9 +7,7 @@ use std::{
}; };
#[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)] #[derive(Hash, PartialEq, Eq, Debug, Clone, Copy)]
pub struct PositionND<const DIMS: usize> { pub struct PositionND<const DIMS: usize>(pub [i64; DIMS]);
pub points: [i64; DIMS],
}
pub type Position2D = PositionND<2>; pub type Position2D = PositionND<2>;
@ -21,7 +19,7 @@ where I: TryInto<i64> + Copy
for i in 0..D { for i in 0..D {
points[i] = s[i].try_into().unwrap_or_else(|_| panic!("number did not fit in target type")) points[i] = s[i].try_into().unwrap_or_else(|_| panic!("number did not fit in target type"))
} }
Self { points } Self(points)
} }
} }
@ -31,7 +29,7 @@ pub const fn num_neighbors(d: usize) -> usize {
impl<const DIMS: usize> PositionND<DIMS> { impl<const DIMS: usize> PositionND<DIMS> {
pub const fn zero() -> Self { pub const fn zero() -> Self {
PositionND { points: [0; DIMS] } PositionND([0; DIMS])
} }
pub fn from_padded(slice: &[i64]) -> PositionND<DIMS> { pub fn from_padded(slice: &[i64]) -> PositionND<DIMS> {
@ -40,7 +38,7 @@ impl<const DIMS: usize> PositionND<DIMS> {
for i in 0..(DIMS.min(slice.len())) { for i in 0..(DIMS.min(slice.len())) {
points[i] = slice[i]; points[i] = slice[i];
} }
PositionND { points } PositionND(points)
} }
pub fn neighbors(&self) -> [PositionND<DIMS>; num_neighbors(DIMS)] pub fn neighbors(&self) -> [PositionND<DIMS>; num_neighbors(DIMS)]
@ -56,12 +54,12 @@ impl<const DIMS: usize> PositionND<DIMS> {
impl PositionND<2> { impl PositionND<2> {
pub fn neighbors_no_diagonals_only_positive(&self) -> [PositionND<2>; 2] { pub fn neighbors_no_diagonals_only_positive(&self) -> [PositionND<2>; 2] {
let PositionND::<2> { points: [x, y] } = *self; let PositionND::<2>([x, y]) = *self;
[[x + 1, y].into(), [x, y + 1].into()] [[x + 1, y].into(), [x, y + 1].into()]
} }
pub fn neighbors_no_diagonals(&self) -> [PositionND<2>; 4] { pub fn neighbors_no_diagonals(&self) -> [PositionND<2>; 4] {
let PositionND::<2> { points: [x, y] } = *self; let PositionND::<2>([x, y]) = *self;
[[x + 1, y].into(), [x, y + 1].into(), [x - 1, y].into(), [x, y - 1].into()] [[x + 1, y].into(), [x, y + 1].into(), [x - 1, y].into(), [x, y - 1].into()]
} }
} }
@ -115,7 +113,7 @@ impl<const D: usize> Mul<i64> for PositionND<D> {
type Output = PositionND<D>; type Output = PositionND<D>;
fn mul(mut self, rhs: i64) -> Self::Output { fn mul(mut self, rhs: i64) -> Self::Output {
for p in self.points.iter_mut() { for p in self.0.iter_mut() {
*p *= rhs; *p *= rhs;
} }
self self
@ -126,7 +124,7 @@ impl<const D: usize> Add<PositionND<D>> for PositionND<D> {
type Output = PositionND<D>; type Output = PositionND<D>;
fn add(mut self, rhs: PositionND<D>) -> Self::Output { fn add(mut self, rhs: PositionND<D>) -> Self::Output {
for (x, y) in self.points.iter_mut().zip(rhs.points) { for (x, y) in self.0.iter_mut().zip(rhs.0) {
*x += y; *x += y;
} }
self self
@ -137,7 +135,7 @@ impl<const D: usize> Sub<PositionND<D>> for PositionND<D> {
type Output = PositionND<D>; type Output = PositionND<D>;
fn sub(mut self, rhs: PositionND<D>) -> Self::Output { fn sub(mut self, rhs: PositionND<D>) -> Self::Output {
for (x, y) in self.points.iter_mut().zip(rhs.points) { for (x, y) in self.0.iter_mut().zip(rhs.0) {
*x -= y; *x -= y;
} }
self self
@ -161,72 +159,72 @@ mod tests {
#[test] #[test]
fn test_neighbors_2d() { fn test_neighbors_2d() {
let p = PositionND { points: [0, 0] }; let p = PositionND([0, 0]);
let n = p.neighbors(); let n = p.neighbors();
assert_eq!( assert_eq!(
n, n,
[ [
PositionND { points: [-1, -1] }, PositionND([-1, -1]),
PositionND { points: [-1, 0] }, PositionND([-1, 0]),
PositionND { points: [-1, 1] }, PositionND([-1, 1]),
PositionND { points: [0, -1] }, PositionND([0, -1]),
PositionND { points: [0, 1] }, PositionND([0, 1]),
PositionND { points: [1, -1] }, PositionND([1, -1]),
PositionND { points: [1, 0] }, PositionND([1, 0]),
PositionND { points: [1, 1] }, PositionND([1, 1]),
] ]
); );
let p = PositionND { points: [1, 1] }; let p = PositionND([1, 1]);
let n = p.neighbors(); let n = p.neighbors();
assert_eq!( assert_eq!(
n, n,
[ [
PositionND { points: [0, 0] }, PositionND([0, 0]),
PositionND { points: [0, 1] }, PositionND([0, 1]),
PositionND { points: [0, 2] }, PositionND([0, 2]),
PositionND { points: [1, 0] }, PositionND([1, 0]),
PositionND { points: [1, 2] }, PositionND([1, 2]),
PositionND { points: [2, 0] }, PositionND([2, 0]),
PositionND { points: [2, 1] }, PositionND([2, 1]),
PositionND { points: [2, 2] }, PositionND([2, 2]),
] ]
) )
} }
#[test] #[test]
fn test_neighbors_3d() { fn test_neighbors_3d() {
let p = PositionND { points: [0, 0, 0] }; let p = PositionND([0, 0, 0]);
let n = p.neighbors(); let n = p.neighbors();
assert_eq!( assert_eq!(
n, n,
[ [
PositionND { points: [-1, -1, -1] }, PositionND([-1, -1, -1]),
PositionND { points: [-1, -1, 0] }, PositionND([-1, -1, 0]),
PositionND { points: [-1, -1, 1] }, PositionND([-1, -1, 1]),
PositionND { points: [-1, 0, -1] }, PositionND([-1, 0, -1]),
PositionND { points: [-1, 0, 0] }, PositionND([-1, 0, 0]),
PositionND { points: [-1, 0, 1] }, PositionND([-1, 0, 1]),
PositionND { points: [-1, 1, -1] }, PositionND([-1, 1, -1]),
PositionND { points: [-1, 1, 0] }, PositionND([-1, 1, 0]),
PositionND { points: [-1, 1, 1] }, PositionND([-1, 1, 1]),
PositionND { points: [0, -1, -1] }, PositionND([0, -1, -1]),
PositionND { points: [0, -1, 0] }, PositionND([0, -1, 0]),
PositionND { points: [0, -1, 1] }, PositionND([0, -1, 1]),
PositionND { points: [0, 0, -1] }, PositionND([0, 0, -1]),
PositionND { points: [0, 0, 1] }, PositionND([0, 0, 1]),
PositionND { points: [0, 1, -1] }, PositionND([0, 1, -1]),
PositionND { points: [0, 1, 0] }, PositionND([0, 1, 0]),
PositionND { points: [0, 1, 1] }, PositionND([0, 1, 1]),
PositionND { points: [1, -1, -1] }, PositionND([1, -1, -1]),
PositionND { points: [1, -1, 0] }, PositionND([1, -1, 0]),
PositionND { points: [1, -1, 1] }, PositionND([1, -1, 1]),
PositionND { points: [1, 0, -1] }, PositionND([1, 0, -1]),
PositionND { points: [1, 0, 0] }, PositionND([1, 0, 0]),
PositionND { points: [1, 0, 1] }, PositionND([1, 0, 1]),
PositionND { points: [1, 1, -1] }, PositionND([1, 1, -1]),
PositionND { points: [1, 1, 0] }, PositionND([1, 1, 0]),
PositionND { points: [1, 1, 1] }, PositionND([1, 1, 1]),
] ]
); );
} }

View File

@ -1,3 +1,5 @@
#![feature(test)] #![allow(incomplete_features)]
#![feature(test, generic_const_exprs)]
pub mod common; pub mod common;
pub mod grid;
pub mod teststuff; pub mod teststuff;