rbe/deriv_n.rs
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 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
use itertools::cloned;
use std::fmt::Debug;
/// Return an iterator that generates variants of the vector applying to each
/// element the function `F`
///
/// 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`.
///
/// ```
/// use rbe::deriv_n;
///
/// let vec = vec![1,2,3];
/// let sets = deriv_n(vec, |x: &i32| { Some(x + 100)}).collect::<Vec<_>>();
/// assert_eq!(sets, vec![
/// vec![101, 2, 3],
/// vec![1, 102, 3],
/// vec![1, 2, 103]
/// ])
///
/// ```
///
/// A similar example which doesn't generate iterator for the value 2
///
/// ```
/// use rbe::deriv_n;
///
/// let vec = vec![1,2,3];
/// let sets = deriv_n(vec, |x: &i32| {
/// match &x {
/// 2 => None,
/// _ => Some(x + 100)
/// }
/// }).collect::<Vec<_>>();
/// assert_eq!(sets, vec![
/// vec![101, 2, 3],
/// vec![1, 2, 103]
/// ])
///
/// ```
pub fn deriv_n<T, F>(v: Vec<T>, d: F) -> DerivN<T, F> {
DerivN {
source: v,
pos: 0,
deriv: d,
}
}
/// An adaptor of a `Vec<T>` that generates an iterator that contains variants of the vector
/// applying function `F` to each element.
///
/// The function `F` returns an `Option<T>` which means that if it returns `None`
/// that row is skipped while if it returns `Some(x)` then that value will be replaced by `x`.
///
///
pub struct DerivN<T, F> {
source: Vec<T>,
pos: usize,
deriv: F,
}
impl<T, F: FnMut(&T) -> Option<T>> Iterator for DerivN<T, F>
where
T: Clone + Debug,
{
type Item = Vec<T>;
fn next(&mut self) -> Option<Self::Item> {
if self.pos < self.source.len() {
let mut cloned: Vec<T> = cloned(self.source.iter()).collect();
let current = &cloned[self.pos];
match (self.deriv)(current) {
None => {
// If it returns None we continue with the next position
self.pos += 1;
Self::next(self)
}
Some(d) => {
cloned[self.pos] = d;
self.pos += 1;
Some(cloned)
}
}
} else {
None
}
}
}
#[cfg(test)]
mod tests {
use crate::deriv_n;
#[test]
fn example_deriv_n() {
let vec = vec![1, 2, 3];
let sets = deriv_n(vec, |x: &i32| Some(x + 100)).collect::<Vec<_>>();
assert_eq!(
sets,
vec![vec![101, 2, 3], vec![1, 102, 3], vec![1, 2, 103]]
)
}
#[test]
fn test_deriv_n() {
#[derive(Debug, Clone, PartialEq)]
enum R {
A(i32),
B(i32),
C(i32),
D(Box<R>),
}
impl R {
fn deriv(&self) -> Option<R> {
match *self {
R::C(_) => None,
_ => Some(R::D(Box::new(self.clone()))),
}
}
}
let vs: Vec<R> = vec![R::A(1), R::B(2), R::C(4), R::A(3)];
let mut results = deriv_n(vs, R::deriv);
assert_eq!(
vec![R::D(Box::new(R::A(1))), R::B(2), R::C(4), R::A(3)],
results.next().unwrap()
);
assert_eq!(
vec![R::A(1), R::D(Box::new(R::B(2))), R::C(4), R::A(3)],
results.next().unwrap()
);
assert_eq!(
vec![R::A(1), R::B(2), R::C(4), R::D(Box::new(R::A(3)))],
results.next().unwrap()
);
assert_eq!(None, results.next());
}
}