diff --git a/2020/src/bin/day11.rs b/2020/src/bin/day11.rs index b3fc805..4dfe377 100644 --- a/2020/src/bin/day11.rs +++ b/2020/src/bin/day11.rs @@ -40,7 +40,7 @@ impl Default for Tile { } } -type Parsed = HashMap; +type Parsed = HashMap, 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 usize>(previous: &mut Parsed, count_neighbors: F, limit: usize) -> bool { +fn make_step, &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 usize>(previous: &mut Parsed, count_ changed } -fn move_until_equilibrium usize>(mut parsed: Parsed, count_neighbors: F, limit: usize) -> usize { +fn move_until_equilibrium, &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); diff --git a/2020/src/grid.rs b/2020/src/grid.rs index 13afb59..325b805 100644 --- a/2020/src/grid.rs +++ b/2020/src/grid.rs @@ -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(coordinates: &HashMap) -> String { +pub fn draw_ascii(coordinates: &HashMap, T, S>) -> String { let b = get_boundaries(&coordinates.keys().collect::>()); 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::() }), "\n", diff --git a/2020/src/grid/position.rs b/2020/src/grid/position.rs index ce85609..92df969 100644 --- a/2020/src/grid/position.rs +++ b/2020/src/grid/position.rs @@ -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 PositionND { 3 => { for (i, n) in iproduct!((-1..=1), (-1..=1), (-1..=1)) .filter(|t| t != &(0, 0, 0)) - .map(|(x, y, z)| PositionND::::from_padded(&[self.points[0]+x, self.points[1]+y, self.points[2]+z])) + .map(|(x, y, z)| PositionND::::from_padded(&[self.points[0] + x, self.points[1] + y, self.points[2] + z])) .enumerate() { out[i] = n; @@ -96,7 +96,9 @@ impl PositionND { 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::::from_padded(&[self.points[0]+x, self.points[1]+y, self.points[2]+z, self.points[3]+w])) + .map(|(x, y, z, w)| { + PositionND::::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 PositionND { */ } +impl Mul for PositionND { + type Output = PositionND; + + 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 Add> for PositionND { type Output = PositionND;