rbe/
deriv_n.rs

1use itertools::cloned;
2use std::fmt::Debug;
3
4/// Return an iterator that generates variants of the vector applying to each
5/// element the function `F`
6///
7/// In case the value of `F` is None, the row will be skipped while if the value is `Some(x)`, then the corresponding element will be replaced by `x`.
8///
9/// ```
10/// use rbe::deriv_n;
11///
12/// let vec = vec![1,2,3];
13/// let sets = deriv_n(vec, |x: &i32| { Some(x + 100)}).collect::<Vec<_>>();
14/// assert_eq!(sets, vec![
15///   vec![101, 2, 3],
16///   vec![1, 102, 3],
17///   vec![1, 2, 103]
18/// ])
19///
20/// ```
21///
22/// A similar example which doesn't generate iterator for the value 2
23///
24/// ```
25/// use rbe::deriv_n;
26///
27/// let vec = vec![1,2,3];
28/// let sets = deriv_n(vec, |x: &i32| {
29///   match &x {
30///     2 => None,
31///     _ => Some(x + 100)
32///   }
33/// }).collect::<Vec<_>>();
34/// assert_eq!(sets, vec![
35///   vec![101, 2, 3],
36///   vec![1, 2, 103]
37/// ])
38///
39/// ```
40pub fn deriv_n<T, F>(v: Vec<T>, d: F) -> DerivN<T, F> {
41    DerivN {
42        source: v,
43        pos: 0,
44        deriv: d,
45    }
46}
47
48/// An adaptor of a `Vec<T>` that generates an iterator that contains variants of the vector
49/// applying function `F` to each element.
50///
51/// The function `F` returns an `Option<T>` which means that if it returns `None`
52/// that row is skipped while if it returns `Some(x)` then that value will be replaced by `x`.
53///
54///
55pub struct DerivN<T, F> {
56    source: Vec<T>,
57    pos: usize,
58    deriv: F,
59}
60
61impl<T, F: FnMut(&T) -> Option<T>> Iterator for DerivN<T, F>
62where
63    T: Clone + Debug,
64{
65    type Item = Vec<T>;
66
67    fn next(&mut self) -> Option<Self::Item> {
68        if self.pos < self.source.len() {
69            let mut cloned: Vec<T> = cloned(self.source.iter()).collect();
70            let current = &cloned[self.pos];
71            match (self.deriv)(current) {
72                None => {
73                    // If it returns None we continue with the next position
74                    self.pos += 1;
75                    Self::next(self)
76                }
77                Some(d) => {
78                    cloned[self.pos] = d;
79                    self.pos += 1;
80                    Some(cloned)
81                }
82            }
83        } else {
84            None
85        }
86    }
87}
88
89#[cfg(test)]
90mod tests {
91    use crate::deriv_n;
92
93    #[test]
94    fn example_deriv_n() {
95        let vec = vec![1, 2, 3];
96
97        let sets = deriv_n(vec, |x: &i32| Some(x + 100)).collect::<Vec<_>>();
98        assert_eq!(
99            sets,
100            vec![vec![101, 2, 3], vec![1, 102, 3], vec![1, 2, 103]]
101        )
102    }
103
104    #[test]
105    fn test_deriv_n() {
106        #[derive(Debug, Clone, PartialEq)]
107        enum R {
108            A(i32),
109            B(i32),
110            C(i32),
111            D(Box<R>),
112        }
113
114        impl R {
115            fn deriv(&self) -> Option<R> {
116                match *self {
117                    R::C(_) => None,
118                    _ => Some(R::D(Box::new(self.clone()))),
119                }
120            }
121        }
122
123        let vs: Vec<R> = vec![R::A(1), R::B(2), R::C(4), R::A(3)];
124        let mut results = deriv_n(vs, R::deriv);
125        assert_eq!(
126            vec![R::D(Box::new(R::A(1))), R::B(2), R::C(4), R::A(3)],
127            results.next().unwrap()
128        );
129        assert_eq!(
130            vec![R::A(1), R::D(Box::new(R::B(2))), R::C(4), R::A(3)],
131            results.next().unwrap()
132        );
133        assert_eq!(
134            vec![R::A(1), R::B(2), R::C(4), R::D(Box::new(R::A(3)))],
135            results.next().unwrap()
136        );
137        assert_eq!(None, results.next());
138    }
139}