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 {
|
fn read_input() -> String {
|
||||||
read_file(11)
|
read_file(11)
|
||||||
|
@ -50,15 +50,20 @@ fn parse_input(raw: &str) -> Parsed {
|
||||||
raw.lines()
|
raw.lines()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.flat_map(move |(y, l)| {
|
.flat_map(move |(y, l)| {
|
||||||
l.chars()
|
l.chars().enumerate().map(move |(x, c)| {
|
||||||
.enumerate()
|
(
|
||||||
.map(move |(x, c)| (Position2D { x: x as i64, y: y as i64 }, Tile::from(c)))
|
PositionND {
|
||||||
|
points: [x as i64, y as i64],
|
||||||
|
},
|
||||||
|
Tile::from(c),
|
||||||
|
)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn occupied_neighbors(pos: &Position2D, grid: &Parsed) -> usize {
|
fn occupied_neighbors(pos: &PositionND<2>, grid: &Parsed) -> usize {
|
||||||
pos.neighbors()
|
pos.neighbors()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|p| grid.get(&p).unwrap_or(&Tile::Floor) == &Tile::Occupied)
|
.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)];
|
const DIRECTIONS: [(i64, i64); 8] = [(0, 1), (1, 0), (1, 1), (0, -1), (-1, 0), (-1, -1), (-1, 1), (1, -1)];
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn neighbors_in_vision(pos: &Position2D, grid: &Parsed) -> usize {
|
fn neighbors_in_vision(pos: &PositionND<2>, grid: &Parsed) -> usize {
|
||||||
DIRECTIONS
|
IntoIterator::into_iter(DIRECTIONS)
|
||||||
.iter()
|
.map(|(x, y)| PositionND { points: [x, y] })
|
||||||
.map(|t| Position2D::from(*t))
|
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
(1..)
|
(1..)
|
||||||
.find_map(|n| match grid.get(&(*pos + (p * n))) {
|
.find_map(|n| match grid.get(&(*pos + (p * n))) {
|
||||||
|
@ -85,7 +89,7 @@ fn neighbors_in_vision(pos: &Position2D, grid: &Parsed) -> usize {
|
||||||
.count()
|
.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 readonly = previous.to_owned();
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
for (pos, tile) in previous.iter_mut() {
|
for (pos, tile) in previous.iter_mut() {
|
||||||
|
@ -108,7 +112,7 @@ fn make_step<F: Fn(&Position2D, &Parsed) -> usize>(previous: &mut Parsed, count_
|
||||||
changed
|
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) {}
|
while make_step(&mut parsed, &count_neighbors, limit) {}
|
||||||
parsed.iter().filter(|(_, t)| t == &&Tile::Occupied).count()
|
parsed.iter().filter(|(_, t)| t == &&Tile::Occupied).count()
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,20 +38,20 @@ struct Boundaries {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
fn get_boundaries(input: &[&Position2D]) -> Boundaries {
|
fn get_boundaries(input: &[&PositionND<2>]) -> Boundaries {
|
||||||
let x_min = input.iter().min_by_key(|k| k.x).map(|p| p.x).unwrap_or(0);
|
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.x).map(|p| p.x).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.y).map(|p| p.y).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.y).map(|p| p.y).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 }
|
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<_>>());
|
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(&(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>()
|
.collect::<String>()
|
||||||
}),
|
}),
|
||||||
"\n",
|
"\n",
|
||||||
|
|
|
@ -3,7 +3,7 @@ use super::direction::*;
|
||||||
use impl_ops::*;
|
use impl_ops::*;
|
||||||
use itertools::iproduct;
|
use itertools::iproduct;
|
||||||
use std::{
|
use std::{
|
||||||
convert::TryInto, hash::Hash, ops, ops::{Add, AddAssign}
|
convert::TryInto, hash::Hash, ops::{self, Add, AddAssign, Mul}
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Position
|
pub trait Position
|
||||||
|
@ -96,7 +96,9 @@ impl<const DIMS: usize> PositionND<DIMS> {
|
||||||
4 => {
|
4 => {
|
||||||
for (i, n) in iproduct!((-1..=1), (-1..=1), (-1..=1), (-1..=1))
|
for (i, n) in iproduct!((-1..=1), (-1..=1), (-1..=1), (-1..=1))
|
||||||
.filter(|t| t != &(0, 0, 0, 0))
|
.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()
|
.enumerate()
|
||||||
{
|
{
|
||||||
out[i] = n;
|
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> {
|
impl<const D: usize> Add<PositionND<D>> for PositionND<D> {
|
||||||
type Output = PositionND<D>;
|
type Output = PositionND<D>;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user