Migrate day 11 to PositionND
This commit is contained in:
parent
eee3183dc0
commit
98b8a9c81c
|
@ -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);
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user