From 813210ea84ed240a3bf3f81a53d3b972228757ae Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Thu, 16 Dec 2021 21:01:26 -0500 Subject: lots of refactoring --- src/util/grid.rs | 216 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 src/util/grid.rs (limited to 'src/util/grid.rs') diff --git a/src/util/grid.rs b/src/util/grid.rs new file mode 100644 index 0000000..47e10fb --- /dev/null +++ b/src/util/grid.rs @@ -0,0 +1,216 @@ +#[derive(Copy, Clone, Hash, Eq, PartialEq)] +pub struct Row(pub usize); +#[derive(Copy, Clone, Hash, Eq, PartialEq)] +pub struct Col(pub usize); + +#[derive(Default, Clone)] +pub struct GridRow { + cells: Vec, +} + +impl GridRow { + pub fn iter(&self) -> impl Iterator + Clone { + self.cells.iter() + } +} + +impl std::ops::Index for GridRow { + type Output = T; + fn index(&self, col: Col) -> &Self::Output { + &self.cells[col.0] + } +} + +impl std::ops::IndexMut for GridRow { + fn index_mut(&mut self, col: Col) -> &mut Self::Output { + &mut self.cells[col.0] + } +} + +#[derive(Default, Clone)] +pub struct Grid { + rows: Vec>, +} + +impl Grid { + pub fn grow(&mut self, rows: Row, cols: Col) { + self.rows + .resize_with(rows.0.max(self.rows.len()), GridRow::default); + for row in &mut self.rows { + row.cells + .resize_with(cols.0.max(row.cells.len()), T::default); + } + } + + pub fn rows(&self) -> Row { + Row(self.rows.len()) + } + + pub fn cols(&self) -> Col { + Col(self.rows[0].cells.len()) + } + + pub fn cells(&self) -> impl Iterator { + self.rows.iter().flat_map(|row| row.cells.iter()) + } + + pub fn cells_mut(&mut self) -> impl Iterator { + self.rows.iter_mut().flat_map(|row| row.cells.iter_mut()) + } + + pub fn indexed_cells(&self) -> impl Iterator { + self.rows.iter().enumerate().flat_map(|(i, row)| { + row.cells + .iter() + .enumerate() + .map(move |(j, cell)| ((Row(i), Col(j)), cell)) + }) + } + + pub fn indexed_cells_mut( + &mut self, + ) -> impl Iterator { + self.rows.iter_mut().enumerate().flat_map(|(i, row)| { + row.cells + .iter_mut() + .enumerate() + .map(move |(j, cell)| ((Row(i), Col(j)), cell)) + }) + } + + pub fn adjacent(&self, row: Row, col: Col, diagonal: bool) -> Adjacent { + Adjacent { + row: row.0, + col: col.0, + rows: self.rows().0, + cols: self.cols().0, + diagonal, + pos: 0, + } + } +} + +impl Grid { + pub fn display_packed char>( + &self, + f: F, + ) -> DisplayPacked { + DisplayPacked(self, f) + } +} + +impl std::fmt::Display for Grid { + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> Result<(), std::fmt::Error> { + for row in &self.rows { + for col in &row.cells { + write!(f, "{} ", col)?; + } + writeln!(f)?; + } + Ok(()) + } +} + +impl std::ops::Index for Grid { + type Output = GridRow; + fn index(&self, row: Row) -> &Self::Output { + &self.rows[row.0] + } +} + +impl std::ops::IndexMut for Grid { + fn index_mut(&mut self, row: Row) -> &mut Self::Output { + &mut self.rows[row.0] + } +} + +impl FromIterator> for Grid { + fn from_iter(iter: I) -> Self + where + I: IntoIterator>, + { + Self { + rows: iter.into_iter().map(|v| GridRow { cells: v }).collect(), + } + } +} + +impl FromIterator<((Row, Col), T)> for Grid { + fn from_iter(iter: I) -> Self + where + I: IntoIterator, + { + let mut self_ = Self::default(); + for ((row, col), cell) in iter { + self_.grow(Row(row.0 + 1), Col(col.0 + 1)); + self_[row][col] = cell; + } + self_ + } +} + +pub struct DisplayPacked< + 'a, + T: Default + Clone + std::fmt::Display, + F: Fn(&'a T) -> char, +>(&'a Grid, F); + +impl<'a, T: Default + Clone + std::fmt::Display, F: Fn(&'a T) -> char> + std::fmt::Display for DisplayPacked<'a, T, F> +{ + fn fmt( + &self, + f: &mut std::fmt::Formatter<'_>, + ) -> Result<(), std::fmt::Error> { + for row in &self.0.rows { + for col in &row.cells { + write!(f, "{}", self.1(col))?; + } + writeln!(f)?; + } + Ok(()) + } +} + +pub struct Adjacent { + row: usize, + col: usize, + rows: usize, + cols: usize, + diagonal: bool, + pos: u8, +} + +impl Iterator for Adjacent { + type Item = (Row, Col); + + fn next(&mut self) -> Option { + loop { + if self.pos >= 9 { + return None; + } + let pos_row = self.pos / 3; + let pos_col = self.pos - pos_row * 3; + self.pos += 1; + if pos_row == 0 && self.row == 0 + || pos_col == 0 && self.col == 0 + || pos_row == 2 && self.row == self.rows - 1 + || pos_col == 2 && self.col == self.cols - 1 + || pos_row == 1 && pos_col == 1 + || (!self.diagonal + && ((pos_row == pos_col) + || (pos_row == 2 && pos_col == 0) + || (pos_row == 0 && pos_col == 2))) + { + continue; + } + return Some(( + Row(self.row + usize::from(pos_row) - 1), + Col(self.col + usize::from(pos_col) - 1), + )); + } + } +} -- cgit v1.2.3-54-g00ecf