1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
//! Check whether a digraph contains a walk.
//!
//! A sequence of vertices is a walk in a digraph if each pair of consecutive
//! vertices in the sequence is an arc in the digraph.
//!
//! # Examples
//!
//! ```
//! use graaf::{
//! AdjacencyList,
//! Circuit,
//! HasWalk,
//! };
//!
//! let digraph = AdjacencyList::circuit(2);
//!
//! assert!(digraph.has_walk(&[0, 1]));
//! assert!(digraph.has_walk(&[1, 0]));
//!
//! assert!(!digraph.has_walk(&[0]));
//! assert!(!digraph.has_walk(&[1]));
//! assert!(!digraph.has_walk(&[2]));
//! assert!(!digraph.has_walk(&[0, 0]));
//! assert!(!digraph.has_walk(&[1, 1]));
//! assert!(!digraph.has_walk(&[0, 2]));
//! ```
use crate::HasArc;
/// Check whether a digraph contains a walk.
///
/// # How do I implement `HasWalk`
///
/// Provide an implementation of `has_walk` that returns whether the sequence
/// is a walk in the digraph OR implement `HasArc`.
///
/// ```
/// use {
/// graaf::{
/// Circuit,
/// HasWalk,
/// },
/// std::collections::BTreeSet,
/// };
///
/// struct AdjacencyList {
/// pub arcs: BTreeSet<(usize, usize)>,
/// }
///
/// impl HasWalk for AdjacencyList {
/// fn has_walk(&self, walk: &[usize]) -> bool {
/// let mut arcs = walk.iter().zip(walk.iter().skip(1));
///
/// arcs.clone().count() > 0
/// && arcs.all(|(&u, &v)| self.arcs.contains(&(u, v)))
/// }
/// }
///
/// let digraph = AdjacencyList {
/// arcs: BTreeSet::from([(0, 1), (1, 0)]),
/// };
///
/// assert!(digraph.has_walk(&[0, 1]));
/// assert!(digraph.has_walk(&[1, 0]));
/// ```
pub trait HasWalk {
/// Check whether the sequence is a walk in the digraph.
///
/// # Arguments
///
/// * `walk`: A sequence of vertices.
///
/// # Examples
///
/// ```
/// use graaf::{
/// AdjacencyList,
/// Circuit,
/// HasWalk,
/// };
///
/// let digraph = AdjacencyList::circuit(2);
///
/// assert!(digraph.has_walk(&[0, 1]));
/// assert!(digraph.has_walk(&[1, 0]));
///
/// assert!(!digraph.has_walk(&[0]));
/// assert!(!digraph.has_walk(&[1]));
/// assert!(!digraph.has_walk(&[2]));
/// assert!(!digraph.has_walk(&[0, 0]));
/// assert!(!digraph.has_walk(&[1, 1]));
/// assert!(!digraph.has_walk(&[0, 2]));
/// ```
#[must_use]
fn has_walk(&self, walk: &[usize]) -> bool;
}
impl<D> HasWalk for D
where
D: HasArc,
{
fn has_walk(&self, walk: &[usize]) -> bool {
let mut arcs = walk.iter().zip(walk.iter().skip(1));
arcs.clone().count() > 0 && arcs.all(|(&u, &v)| self.has_arc(u, v))
}
}