From 17b710ecb1039e9343e01a50620e763580c9ec90 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Tue, 21 Dec 2021 17:19:10 -0500 Subject: reorganize a bit --- src/grid.rs | 252 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 5 +- src/parse.rs | 65 ++++++++++++++ src/prelude.rs | 4 +- src/util.rs | 2 - src/util/grid.rs | 252 ------------------------------------------------------ src/util/parse.rs | 65 -------------- 7 files changed, 322 insertions(+), 323 deletions(-) create mode 100644 src/grid.rs create mode 100644 src/parse.rs delete mode 100644 src/util.rs delete mode 100644 src/util/grid.rs delete mode 100644 src/util/parse.rs diff --git a/src/grid.rs b/src/grid.rs new file mode 100644 index 0000000..c0607c0 --- /dev/null +++ b/src/grid.rs @@ -0,0 +1,252 @@ +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +pub struct Row(pub usize); +#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] +pub struct Col(pub usize); + +impl std::ops::Add for Row { + type Output = Self; + fn add(self, other: usize) -> Self::Output { + Self(self.0 + other) + } +} + +impl std::ops::Add for usize { + type Output = Row; + fn add(self, other: Row) -> Self::Output { + Row(self + other.0) + } +} + +impl std::ops::Add for Col { + type Output = Self; + fn add(self, other: usize) -> Self::Output { + Self(self.0 + other) + } +} + +impl std::ops::Add for usize { + type Output = Col; + fn add(self, other: Col) -> Self::Output { + Col(self + other.0) + } +} + +#[derive(Default, Clone, Debug)] +pub struct GridRow { + cells: Vec, +} + +impl GridRow { + pub fn iter(&self) -> impl Iterator + Clone { + self.cells.iter() + } + + pub fn get(&self, col: Col) -> Option<&T> { + self.cells.get(col.0) + } +} + +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, Debug)] +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 get(&self, row: Row) -> Option<&GridRow> { + self.rows.get(row.0) + } + + 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), + )); + } + } +} diff --git a/src/main.rs b/src/main.rs index 7cb8a72..aa6ad88 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,8 +9,9 @@ #![allow(clippy::collapsible_if)] #![allow(clippy::comparison_chain)] -mod prelude; -mod util; +pub mod grid; +pub mod parse; +pub mod prelude; #[path = "2020/mod.rs"] mod year2020; diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..903ad2f --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,65 @@ +use crate::prelude::*; + +pub fn data(year: u16, day: u16) -> Result { + File::open(format!("data/{}/{}.txt", year, day)).map_err(|e| anyhow!(e)) +} + +pub fn lines(fh: File) -> impl Iterator { + let fh = std::io::BufReader::new(fh); + fh.lines().map(|res| res.unwrap()) +} + +pub fn split(fh: File, sep: u8) -> impl Iterator { + let fh = std::io::BufReader::new(fh); + fh.split(sep) + .map(|res| String::from_utf8(res.unwrap()).unwrap()) +} + +pub fn ints(iter: impl Iterator) -> impl Iterator { + iter.map(|s| s.trim().parse().unwrap()) +} + +pub fn bytes(fh: File) -> impl Iterator { + fh.bytes().map(|res| res.unwrap()) +} + +pub fn string(fh: File) -> String { + let bytes: Vec<_> = bytes(fh).collect(); + String::from_utf8(bytes).unwrap() +} + +pub fn bool_grid( + lines: impl Iterator, + t: u8, + f: u8, +) -> Grid { + lines + .map(|s| { + s.as_bytes() + .iter() + .copied() + .map(|b| { + if b == f { + false + } else if b == t { + true + } else { + panic!("unrecognized character {}", char::from(b)) + } + }) + .collect::>() + }) + .collect() +} + +pub fn digit_grid(lines: impl Iterator) -> Grid { + lines + .map(|s| { + s.as_bytes() + .iter() + .copied() + .map(|b| b - b'0') + .collect::>() + }) + .collect() +} diff --git a/src/prelude.rs b/src/prelude.rs index cd6b8f8..19382dc 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,5 +1,5 @@ -pub use crate::util::grid::{Col, Grid, Row}; -pub use crate::util::parse; +pub use crate::grid::{Col, Grid, Row}; +pub use crate::parse; pub use std::cmp::Ordering; pub use std::collections::VecDeque; diff --git a/src/util.rs b/src/util.rs deleted file mode 100644 index d3687f2..0000000 --- a/src/util.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod grid; -pub mod parse; diff --git a/src/util/grid.rs b/src/util/grid.rs deleted file mode 100644 index c0607c0..0000000 --- a/src/util/grid.rs +++ /dev/null @@ -1,252 +0,0 @@ -#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] -pub struct Row(pub usize); -#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)] -pub struct Col(pub usize); - -impl std::ops::Add for Row { - type Output = Self; - fn add(self, other: usize) -> Self::Output { - Self(self.0 + other) - } -} - -impl std::ops::Add for usize { - type Output = Row; - fn add(self, other: Row) -> Self::Output { - Row(self + other.0) - } -} - -impl std::ops::Add for Col { - type Output = Self; - fn add(self, other: usize) -> Self::Output { - Self(self.0 + other) - } -} - -impl std::ops::Add for usize { - type Output = Col; - fn add(self, other: Col) -> Self::Output { - Col(self + other.0) - } -} - -#[derive(Default, Clone, Debug)] -pub struct GridRow { - cells: Vec, -} - -impl GridRow { - pub fn iter(&self) -> impl Iterator + Clone { - self.cells.iter() - } - - pub fn get(&self, col: Col) -> Option<&T> { - self.cells.get(col.0) - } -} - -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, Debug)] -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 get(&self, row: Row) -> Option<&GridRow> { - self.rows.get(row.0) - } - - 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), - )); - } - } -} diff --git a/src/util/parse.rs b/src/util/parse.rs deleted file mode 100644 index 903ad2f..0000000 --- a/src/util/parse.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::prelude::*; - -pub fn data(year: u16, day: u16) -> Result { - File::open(format!("data/{}/{}.txt", year, day)).map_err(|e| anyhow!(e)) -} - -pub fn lines(fh: File) -> impl Iterator { - let fh = std::io::BufReader::new(fh); - fh.lines().map(|res| res.unwrap()) -} - -pub fn split(fh: File, sep: u8) -> impl Iterator { - let fh = std::io::BufReader::new(fh); - fh.split(sep) - .map(|res| String::from_utf8(res.unwrap()).unwrap()) -} - -pub fn ints(iter: impl Iterator) -> impl Iterator { - iter.map(|s| s.trim().parse().unwrap()) -} - -pub fn bytes(fh: File) -> impl Iterator { - fh.bytes().map(|res| res.unwrap()) -} - -pub fn string(fh: File) -> String { - let bytes: Vec<_> = bytes(fh).collect(); - String::from_utf8(bytes).unwrap() -} - -pub fn bool_grid( - lines: impl Iterator, - t: u8, - f: u8, -) -> Grid { - lines - .map(|s| { - s.as_bytes() - .iter() - .copied() - .map(|b| { - if b == f { - false - } else if b == t { - true - } else { - panic!("unrecognized character {}", char::from(b)) - } - }) - .collect::>() - }) - .collect() -} - -pub fn digit_grid(lines: impl Iterator) -> Grid { - lines - .map(|s| { - s.as_bytes() - .iter() - .copied() - .map(|b| b - b'0') - .collect::>() - }) - .collect() -} -- cgit v1.2.3-54-g00ecf