From e495e7b0e884bd8c74f0e91fd521f388dd2f9b3f Mon Sep 17 00:00:00 2001 From: luca3s <41015240+luca3s@users.noreply.github.com> Date: Tue, 14 May 2024 22:08:34 +0200 Subject: [PATCH 1/4] first try at double ended and sized iter --- src/lib.rs | 73 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 64 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index da5d835..d7c7f3b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1444,7 +1444,8 @@ impl Grid { pub fn iter_rows(&self) -> GridRowIter<'_, T> { GridRowIter { grid: self, - row_index: 0, + row_start_index: 0, + row_end_index: self.rows-1, } } @@ -1646,12 +1647,14 @@ impl From<(&Vec, &usize)> for Grid { } } -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct GridRowIter<'a, T> { grid: &'a Grid, - row_index: usize, + row_start_index: usize, + row_end_index: usize, } -#[derive(Clone)] + +#[derive(Clone, Debug)] pub struct GridColIter<'a, T> { grid: &'a Grid, col_index: usize, @@ -1661,15 +1664,31 @@ impl<'a, T> Iterator for GridRowIter<'a, T> { type Item = StepBy>; fn next(&mut self) -> Option { - let rows = self.grid.rows(); - let row_index = self.row_index; + if self.row_start_index >= self.row_end_index { + return None; + } + + let row_iter = self.grid.iter_row(self.row_start_index); + self.row_start_index += 1; + Some(row_iter) + } + + fn size_hint(&self) -> (usize, Option) { + let size = self.row_end_index - self.row_start_index + 1; + (size, Some(size)) + } +} + +impl<'a, T> ExactSizeIterator for GridRowIter<'a, T> { } - if !(0..rows).contains(&row_index) { +impl<'a, T> DoubleEndedIterator for GridRowIter<'a, T> { + fn next_back(&mut self) -> Option { + if self.row_start_index >= self.row_end_index { return None; } - let row_iter = self.grid.iter_row(row_index); - self.row_index += 1; + let row_iter = self.grid.iter_row(self.row_end_index); + self.row_end_index -= 1; Some(row_iter) } } @@ -1689,6 +1708,28 @@ impl<'a, T> Iterator for GridColIter<'a, T> { self.col_index += 1; Some(row_iter) } + + fn size_hint(&self) -> (usize, Option) { + let cols = self.grid.cols(); + (cols, Some(cols)) + } +} + +impl<'a, T> ExactSizeIterator for GridColIter<'a, T> { } + +impl<'a, T> DoubleEndedIterator for GridColIter<'a, T> { + fn next_back(&mut self) -> Option { + let cols = self.grid.cols(); + let col_index = self.col_index; + + if !(0..cols).contains(&col_index) { + return None; + } + + let row_iter = self.grid.iter_col(col_index); + self.col_index -= 1; + Some(row_iter) + } } #[cfg(test)] @@ -3097,6 +3138,7 @@ mod test { #[allow(clippy::redundant_closure_for_method_calls)] fn iter_rows() { let grid: Grid = grid![[1,2,3][4,5,6]]; + print!("grid: {grid:?}"); let max_by_row: Vec = grid .iter_rows() .map(|row| row.max().unwrap()) @@ -3108,6 +3150,19 @@ mod test { assert_eq!(sum_by_row, vec![1 + 2 + 3, 4 + 5 + 6]); } + #[test] + #[allow(clippy::redundant_closure_for_method_calls)] + fn iter_rows_rev() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + print!("grid: {grid:?}"); + let mut row_iter: core::iter::Rev> = grid.iter_rows().rev(); + print!("rev iter: {row_iter:?}"); + assert!(row_iter.next().unwrap().eq([4,5,7].iter())); + print!("row 1 success"); + assert!(row_iter.next().unwrap().eq([1,2,3].iter())); + print!("row 0 success"); + } + #[test] #[allow(clippy::redundant_closure_for_method_calls)] fn iter_cols() { From 17a258c0674d873691fe083e2c774f65f6e06507 Mon Sep 17 00:00:00 2001 From: luca3s <41015240+luca3s@users.noreply.github.com> Date: Tue, 14 May 2024 23:35:16 +0200 Subject: [PATCH 2/4] all iters implementes and tested --- src/lib.rs | 98 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 70 insertions(+), 28 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d7c7f3b..66f04b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1445,7 +1445,7 @@ impl Grid { GridRowIter { grid: self, row_start_index: 0, - row_end_index: self.rows-1, + row_end_index: self.rows, } } @@ -1467,7 +1467,8 @@ impl Grid { pub fn iter_cols(&self) -> GridColIter<'_, T> { GridColIter { grid: self, - col_index: 0, + col_start_index: 0, + col_end_index: self.cols, } } } @@ -1657,7 +1658,8 @@ pub struct GridRowIter<'a, T> { #[derive(Clone, Debug)] pub struct GridColIter<'a, T> { grid: &'a Grid, - col_index: usize, + col_start_index: usize, + col_end_index: usize, } impl<'a, T> Iterator for GridRowIter<'a, T> { @@ -1674,7 +1676,7 @@ impl<'a, T> Iterator for GridRowIter<'a, T> { } fn size_hint(&self) -> (usize, Option) { - let size = self.row_end_index - self.row_start_index + 1; + let size = self.row_end_index - self.row_start_index; (size, Some(size)) } } @@ -1687,7 +1689,7 @@ impl<'a, T> DoubleEndedIterator for GridRowIter<'a, T> { return None; } - let row_iter = self.grid.iter_row(self.row_end_index); + let row_iter = self.grid.iter_row(self.row_end_index - 1); self.row_end_index -= 1; Some(row_iter) } @@ -1697,21 +1699,18 @@ impl<'a, T> Iterator for GridColIter<'a, T> { type Item = StepBy>; fn next(&mut self) -> Option { - let cols = self.grid.cols(); - let col_index = self.col_index; - - if !(0..cols).contains(&col_index) { + if self.col_start_index >= self.col_end_index { return None; } - let row_iter = self.grid.iter_col(col_index); - self.col_index += 1; - Some(row_iter) + let col_iter = self.grid.iter_col(self.col_start_index); + self.col_start_index += 1; + Some(col_iter) } fn size_hint(&self) -> (usize, Option) { - let cols = self.grid.cols(); - (cols, Some(cols)) + let size = self.col_end_index - self.col_start_index; + (size, Some(size)) } } @@ -1719,16 +1718,13 @@ impl<'a, T> ExactSizeIterator for GridColIter<'a, T> { } impl<'a, T> DoubleEndedIterator for GridColIter<'a, T> { fn next_back(&mut self) -> Option { - let cols = self.grid.cols(); - let col_index = self.col_index; - - if !(0..cols).contains(&col_index) { + if self.col_start_index >= self.col_end_index { return None; } - let row_iter = self.grid.iter_col(col_index); - self.col_index -= 1; - Some(row_iter) + let col_iter = self.grid.iter_col(self.col_end_index - 1); + self.col_end_index -= 1; + Some(col_iter) } } @@ -3154,13 +3150,28 @@ mod test { #[allow(clippy::redundant_closure_for_method_calls)] fn iter_rows_rev() { let grid: Grid = grid![[1,2,3][4,5,6]]; - print!("grid: {grid:?}"); - let mut row_iter: core::iter::Rev> = grid.iter_rows().rev(); - print!("rev iter: {row_iter:?}"); - assert!(row_iter.next().unwrap().eq([4,5,7].iter())); - print!("row 1 success"); - assert!(row_iter.next().unwrap().eq([1,2,3].iter())); - print!("row 0 success"); + let max_by_row: Vec = grid + .iter_rows() + .rev() + .map(|row| row.max().unwrap()) + .copied() + .collect(); + assert_eq!(max_by_row, vec![6, 3]); + + let sum_by_row: Vec = grid.iter_rows().rev().map(|row| row.sum()).collect(); + assert_eq!(sum_by_row, vec![4 + 5 + 6, 1 + 2 + 3]); + } + + #[test] + fn iter_rows_exact_size() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let mut row_iter = grid.iter_rows(); + assert_eq!(row_iter.len(), 2); + assert!(row_iter.next().is_some()); + assert_eq!(row_iter.len(), 1); + assert!(row_iter.next().is_some()); + assert_eq!(row_iter.len(), 0); + assert!(row_iter.next().is_none()); } #[test] @@ -3179,6 +3190,37 @@ mod test { assert_eq!(sum_by_col, vec![1 + 4, 2 + 5, 3 + 6]); } + #[test] + #[allow(clippy::redundant_closure_for_method_calls)] + fn iter_cols_rev() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let max_by_col: Vec = grid + .iter_cols() + .rev() + .map(|col| col.max().unwrap()) + .copied() + .collect(); + + assert_eq!(max_by_col, vec![6, 5, 4]); + + let sum_by_col: Vec = grid.iter_cols().rev().map(|row| row.sum()).collect(); + assert_eq!(sum_by_col, vec![3 + 6, 2 + 5, 1 + 4]); + } + + #[test] + fn iter_cols_exact_size() { + let grid: Grid = grid![[1,2,3][4,5,6]]; + let mut col_iter = grid.iter_cols(); + assert_eq!(col_iter.len(), 3); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 2); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 1); + assert!(col_iter.next().is_some()); + assert_eq!(col_iter.len(), 0); + assert!(col_iter.next().is_none()); + } + #[test] fn remove_row() { let mut grid = grid![[1,2][3,4][5,6]]; From 08cf5295dbcd31c7c161dd7b6fb5c87dafdbe11a Mon Sep 17 00:00:00 2001 From: luca3s <41015240+luca3s@users.noreply.github.com> Date: Tue, 14 May 2024 23:39:29 +0200 Subject: [PATCH 3/4] clean up some diffs --- src/lib.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 66f04b7..d5434c0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1648,14 +1648,14 @@ impl From<(&Vec, &usize)> for Grid { } } -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct GridRowIter<'a, T> { grid: &'a Grid, row_start_index: usize, row_end_index: usize, } -#[derive(Clone, Debug)] +#[derive(Clone)] pub struct GridColIter<'a, T> { grid: &'a Grid, col_start_index: usize, @@ -3134,7 +3134,6 @@ mod test { #[allow(clippy::redundant_closure_for_method_calls)] fn iter_rows() { let grid: Grid = grid![[1,2,3][4,5,6]]; - print!("grid: {grid:?}"); let max_by_row: Vec = grid .iter_rows() .map(|row| row.max().unwrap()) From 394575cbce12d04528a422af382e3d6d0544f2af Mon Sep 17 00:00:00 2001 From: luca3s <41015240+luca3s@users.noreply.github.com> Date: Tue, 14 May 2024 23:57:02 +0200 Subject: [PATCH 4/4] cargo fmt (how can i forget this every time) --- src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index d5434c0..85a9817 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -835,7 +835,7 @@ impl Grid { /// *i += 1; /// println!("value at row {row} and column {col} is: {i}"); /// } - /// + /// /// assert_eq!(grid[(0, 0)], 2); /// assert_eq!(grid[(0, 1)], 3); /// assert_eq!(grid[(1, 0)], 4); @@ -1681,7 +1681,7 @@ impl<'a, T> Iterator for GridRowIter<'a, T> { } } -impl<'a, T> ExactSizeIterator for GridRowIter<'a, T> { } +impl<'a, T> ExactSizeIterator for GridRowIter<'a, T> {} impl<'a, T> DoubleEndedIterator for GridRowIter<'a, T> { fn next_back(&mut self) -> Option { @@ -1714,7 +1714,7 @@ impl<'a, T> Iterator for GridColIter<'a, T> { } } -impl<'a, T> ExactSizeIterator for GridColIter<'a, T> { } +impl<'a, T> ExactSizeIterator for GridColIter<'a, T> {} impl<'a, T> DoubleEndedIterator for GridColIter<'a, T> { fn next_back(&mut self) -> Option {