advent-of-code/common/rust/src/grid.rs

62 lines
1.8 KiB
Rust

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Error {
BadWidth { expected: usize, got: usize },
}
/// A two-dimensional grid of values.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Grid<T> {
width: usize,
height: usize,
rows: Vec<Vec<T>>,
}
impl<T> Grid<T> {
/// Creates a new grid with a given `width` and `height`. The data is given as a [`Vec`] of
/// rows, each row a [`Vec`] of values.
///
/// # Errors
///
/// Returns an error if the given data does not match up with the dimensions.
pub fn from_rows(rows: Vec<Vec<T>>) -> Result<Self, Error> {
let row_len = rows.get(0).map_or(0, Vec::len);
if let Some(err) = rows.iter().map(Vec::len).find_map(|l| {
(l != row_len).then_some(Error::BadWidth {
expected: row_len,
got: l,
})
}) {
return Err(err);
}
Ok(Self {
width: rows.get(0).map_or(0, std::vec::Vec::len),
height: rows.len(),
rows,
})
}
pub fn rows(&self) -> impl Iterator<Item = impl Iterator<Item = &T>> {
self.rows.iter().map(|row| row.iter())
}
pub fn cols(&self) -> impl Iterator<Item = impl Iterator<Item = &T>> {
(0..self.width).map(|i| self.rows.iter().map(move |r| &r[i]))
}
pub fn rows_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut T>> {
self.rows.iter_mut().map(|row| row.iter_mut())
}
/*
pub fn cols_mut(&mut self) -> impl Iterator<Item = impl Iterator<Item = &mut T>> {
(0..self.width).map(move |i| {
self.rows.iter_mut().map(move |r| {
let i: usize = i;
let x: &mut T = &mut r[i];
x
})
})
}
*/
}