Skip to content

Commit 66dbd47

Browse files
Merge #309
309: Add reachable() to Matrix r=samueltardieu a=samueltardieu Co-authored-by: Samuel Tardieu <[email protected]>
2 parents ce41a89 + 96eaf39 commit 66dbd47

File tree

2 files changed

+40
-0
lines changed

2 files changed

+40
-0
lines changed

src/matrix.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
//! Matrix of an arbitrary type and utilities to rotate, transpose, etc.
22
3+
use crate::directed::bfs::bfs_reach;
34
use crate::utils::uint_sqrt;
45
use itertools::iproduct;
56
use itertools::Itertools;
67
use num_traits::Signed;
8+
use std::collections::BTreeSet;
79
use std::error::Error;
810
use std::fmt;
911
use std::ops::{Deref, DerefMut, Index, IndexMut, Neg, Range};
@@ -516,6 +518,27 @@ impl<C> Matrix<C> {
516518
pub fn values_mut(&mut self) -> IterMut<C> {
517519
self.data.iter_mut()
518520
}
521+
522+
/// Return a set of the indices reachable from a candidate starting point
523+
/// and for which the given predicate is valid. This can be used for example
524+
/// to implement a flood-filling algorithm. Since the indices are collected
525+
/// into a vector, they can later be used without keeping a reference on the
526+
/// matrix itself, e.g., to modify the matrix.
527+
pub fn reachable<P>(
528+
&self,
529+
start: (usize, usize),
530+
diagonals: bool,
531+
mut predicate: P,
532+
) -> BTreeSet<(usize, usize)>
533+
where
534+
P: FnMut((usize, usize)) -> bool,
535+
P: Copy,
536+
{
537+
bfs_reach(start, move |&n| {
538+
self.neighbours(n, diagonals).filter(move |&n| predicate(n))
539+
})
540+
.collect()
541+
}
519542
}
520543

521544
impl<C> Index<(usize, usize)> for Matrix<C> {

tests/matrix.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,23 @@ fn empty_neighbours() {
379379
assert_eq!(m.neighbours((10, 10), true).collect::<Vec<_>>(), vec![]);
380380
}
381381

382+
#[test]
383+
fn reachable() {
384+
let m = matrix![[0, 1, 2], [3, 4, 5], [6, 7, 8]];
385+
386+
let indices = m.reachable((1, 0), false, |n| m[n] % 4 != 0);
387+
assert_eq!(
388+
indices.into_iter().collect::<Vec<_>>(),
389+
vec![(1, 0), (2, 0), (2, 1)]
390+
);
391+
392+
let indices = m.reachable((1, 0), true, |n| m[n] % 4 != 0);
393+
assert_eq!(
394+
indices.into_iter().collect::<Vec<_>>(),
395+
vec![(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)]
396+
);
397+
}
398+
382399
#[test]
383400
fn from_rows() {
384401
let m = Matrix::from_rows((1..3).map(|n| (1..5).map(move |x| x * n))).unwrap();

0 commit comments

Comments
 (0)