Day 12
This commit is contained in:
parent
78f7f2db49
commit
04f4adc410
4 changed files with 243 additions and 1 deletions
108
src/util/maps.rs
Normal file
108
src/util/maps.rs
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
use itertools::Itertools;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Direction {
|
||||
North,
|
||||
South,
|
||||
East,
|
||||
West,
|
||||
}
|
||||
|
||||
impl Direction {
|
||||
pub fn all_variants() -> Vec<Self> {
|
||||
vec![Self::North, Self::East, Self::West, Self::South]
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Map<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub map: Vec<Vec<T>>,
|
||||
}
|
||||
|
||||
impl Map<char> {
|
||||
pub fn from_string(string: &str) -> Self {
|
||||
Map::from_2d_vec(
|
||||
string
|
||||
.lines()
|
||||
.filter(|line| !line.is_empty())
|
||||
.map(|line| line.chars().collect())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Map<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
pub fn from_2d_vec(map: Vec<Vec<T>>) -> Self {
|
||||
Self { map }
|
||||
}
|
||||
|
||||
pub fn from_dimensions(width: usize, height: usize, default: T) -> Self {
|
||||
Self {
|
||||
map: vec![vec![default; width]; height],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn travel(&self, x: usize, y: usize, direction: Direction) -> Option<(usize, usize)> {
|
||||
match direction {
|
||||
Direction::North => Some((x, y.checked_sub(1)?)),
|
||||
Direction::South => {
|
||||
if y + 1 < self.height() {
|
||||
Some((x, y + 1))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Direction::West => Some((x.checked_sub(1)?, y)),
|
||||
Direction::East => {
|
||||
if x + 1 < self.width() {
|
||||
Some((x + 1, y))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn travel_get(&self, x: usize, y: usize, direction: Direction) -> Option<T> {
|
||||
let (nx, ny) = self.travel(x, y, direction)?;
|
||||
self.get(nx, ny)
|
||||
}
|
||||
|
||||
pub fn get(&self, x: usize, y: usize) -> Option<T> {
|
||||
Some(*self.map.get(y)?.get(x)?)
|
||||
}
|
||||
|
||||
pub fn set(&mut self, x: usize, y: usize, value: T) {
|
||||
self.map[y][x] = value
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
self.map.len()
|
||||
}
|
||||
|
||||
pub fn width(&self) -> usize {
|
||||
self.map[0].len()
|
||||
}
|
||||
|
||||
pub fn in_bounds(&self, x: usize, y: usize) -> bool {
|
||||
x < self.width() && y < self.height()
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||
self.map.iter().flat_map(|row| row.iter())
|
||||
}
|
||||
|
||||
pub fn coordinates(&self) -> impl Iterator<Item = (usize, usize)> {
|
||||
(0..self.width()).cartesian_product(0..self.height())
|
||||
}
|
||||
|
||||
pub fn enumerate(&self) -> impl Iterator<Item = (usize, usize, &T)> {
|
||||
self.coordinates().map(|(x, y)| (x, y, &self.map[y][x]))
|
||||
}
|
||||
}
|
||||
Reference in a new issue