Migrate day 11 to PositionND

This commit is contained in:
kageru 2021-07-08 19:21:07 +02:00
parent eee3183dc0
commit 98b8a9c81c
Signed by: kageru
GPG Key ID: 8282A2BEA4ADA3D2
3 changed files with 40 additions and 22 deletions

View File

@ -40,7 +40,7 @@ impl Default for Tile {
}
}
type Parsed = HashMap<Position2D, Tile>;
type Parsed = HashMap<PositionND<2>, Tile>;
fn read_input() -> String {
read_file(11)
@ -50,15 +50,20 @@ fn parse_input(raw: &str) -> Parsed {
raw.lines()
.enumerate()
.flat_map(move |(y, l)| {
l.chars()
.enumerate()
.map(move |(x, c)| (Position2D { x: x as i64, y: y as i64 }, Tile::from(c)))
l.chars().enumerate().map(move |(x, c)| {
(
PositionND {
points: [x as i64, y as i64],
},
Tile::from(c),
)
})
})
.collect()
}
#[inline]
fn occupied_neighbors(pos: &Position2D, grid: &Parsed) -> usize {
fn occupied_neighbors(pos: &PositionND<2>, grid: &Parsed) -> usize {
pos.neighbors()
.iter()
.filter(|p| grid.get(&p).unwrap_or(&Tile::Floor) == &Tile::Occupied)
@ -68,10 +73,9 @@ fn occupied_neighbors(pos: &Position2D, grid: &Parsed) -> usize {
const DIRECTIONS: [(i64, i64); 8] = [(0, 1), (1, 0), (1, 1), (0, -1), (-1, 0), (-1, -1), (-1, 1), (1, -1)];
#[inline]
fn neighbors_in_vision(pos: &Position2D, grid: &Parsed) -> usize {
DIRECTIONS
.iter()
.map(|t| Position2D::from(*t))
fn neighbors_in_vision(pos: &PositionND<2>, grid: &Parsed) -> usize {
IntoIterator::into_iter(DIRECTIONS)
.map(|(x, y)| PositionND { points: [x, y] })
.map(|p| {
(1..)
.find_map(|n| match grid.get(&(*pos + (p * n))) {
@ -85,7 +89,7 @@ fn neighbors_in_vision(pos: &Position2D, grid: &Parsed) -> usize {
.count()
}
fn make_step<F: Fn(&Position2D, &Parsed) -> usize>(previous: &mut Parsed, count_neighbors: F, limit: usize) -> bool {
fn make_step<F: Fn(&PositionND<2>, &Parsed) -> usize>(previous: &mut Parsed, count_neighbors: F, limit: usize) -> bool {
let readonly = previous.to_owned();
let mut changed = false;
for (pos, tile) in previous.iter_mut() {
@ -108,7 +112,7 @@ fn make_step<F: Fn(&Position2D, &Parsed) -> usize>(previous: &mut Parsed, count_
changed
}
fn move_until_equilibrium<F: Fn(&Position2D, &Parsed) -> usize>(mut parsed: Parsed, count_neighbors: F, limit: usize) -> usize {
fn move_until_equilibrium<F: Fn(&PositionND<2>, &Parsed) -> usize>(mut parsed: Parsed, count_neighbors: F, limit: usize) -> usize {
while make_step(&mut parsed, &count_neighbors, limit) {}
parsed.iter().filter(|(_, t)| t == &&Tile::Occupied).count()
}
@ -219,7 +223,7 @@ LLL####LL#
assert_eq!(draw_ascii(&grid), draw_ascii(&after_1));
assert_eq!(&grid, &after_1);
assert!( make_step(&mut grid, neighbors_in_vision, 5));
assert!(make_step(&mut grid, neighbors_in_vision, 5));
let after_2 = parse_input(P2_AFTER_2);
assert_eq!(draw_ascii(&grid), draw_ascii(&after_2));
assert_eq!(&grid, &after_2);

View File

@ -38,20 +38,20 @@ struct Boundaries {
}
#[rustfmt::skip]
fn get_boundaries(input: &[&Position2D]) -> Boundaries {
let x_min = input.iter().min_by_key(|k| k.x).map(|p| p.x).unwrap_or(0);
let x_max = input.iter().max_by_key(|k| k.x).map(|p| p.x).unwrap_or(0);
let y_min = input.iter().min_by_key(|k| k.y).map(|p| p.y).unwrap_or(0);
let y_max = input.iter().max_by_key(|k| k.y).map(|p| p.y).unwrap_or(0);
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);
let y_min = input.iter().min_by_key(|k| k.points[1]).map(|p| p.points[1]).unwrap_or(0);
let y_max = input.iter().max_by_key(|k| k.points[1]).map(|p| p.points[1]).unwrap_or(0);
Boundaries { x_min, x_max, y_min, y_max }
}
pub fn draw_ascii<T: Display + Default, S: BuildHasher>(coordinates: &HashMap<Position2D, T, S>) -> String {
pub fn draw_ascii<T: Display + Default, S: BuildHasher>(coordinates: &HashMap<PositionND<2>, T, S>) -> String {
let b = get_boundaries(&coordinates.keys().collect::<Vec<_>>());
join(
(b.y_min..=b.y_max).rev().map(|y| {
(b.x_min..=b.x_max)
.map(|x| coordinates.get(&(x, y).into()).unwrap_or(&T::default()).to_string())
.map(|x| coordinates.get(&PositionND { points: [x, y] }).unwrap_or(&T::default()).to_string())
.collect::<String>()
}),
"\n",

View File

@ -3,7 +3,7 @@ use super::direction::*;
use impl_ops::*;
use itertools::iproduct;
use std::{
convert::TryInto, hash::Hash, ops, ops::{Add, AddAssign}
convert::TryInto, hash::Hash, ops::{self, Add, AddAssign, Mul}
};
pub trait Position
@ -87,7 +87,7 @@ impl<const DIMS: usize> PositionND<DIMS> {
3 => {
for (i, n) in iproduct!((-1..=1), (-1..=1), (-1..=1))
.filter(|t| t != &(0, 0, 0))
.map(|(x, y, z)| PositionND::<DIMS>::from_padded(&[self.points[0]+x, self.points[1]+y, self.points[2]+z]))
.map(|(x, y, z)| PositionND::<DIMS>::from_padded(&[self.points[0] + x, self.points[1] + y, self.points[2] + z]))
.enumerate()
{
out[i] = n;
@ -96,7 +96,9 @@ impl<const DIMS: usize> PositionND<DIMS> {
4 => {
for (i, n) in iproduct!((-1..=1), (-1..=1), (-1..=1), (-1..=1))
.filter(|t| t != &(0, 0, 0, 0))
.map(|(x, y, z, w)| PositionND::<DIMS>::from_padded(&[self.points[0]+x, self.points[1]+y, self.points[2]+z, self.points[3]+w]))
.map(|(x, y, z, w)| {
PositionND::<DIMS>::from_padded(&[self.points[0] + x, self.points[1] + y, self.points[2] + z, self.points[3] + w])
})
.enumerate()
{
out[i] = n;
@ -125,6 +127,18 @@ impl<const DIMS: usize> PositionND<DIMS> {
*/
}
impl<const D: usize> Mul<i64> for PositionND<D> {
type Output = PositionND<D>;
fn mul(self, rhs: i64) -> Self::Output {
let mut points = [0; D];
for i in 0..D {
points[i] = self.points[i] * rhs;
}
PositionND { points }
}
}
impl<const D: usize> Add<PositionND<D>> for PositionND<D> {
type Output = PositionND<D>;