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}