#[inline]
pub fn each_combination<T, F>(values: &[T], r: usize, mut fun: F) -> ()
where
T: Clone,
F: FnMut(&[T]) -> (),
{
let length = values.len();
if r == 0 || r > length {
return;
}
let max_indices0 = length - r;
let mut indices: Vec<usize> = (0..r).collect();
let mut combination: Vec<T> = values[0..r].iter().cloned().collect();
loop {
fun(&combination);
let mut i = r - 1;
indices[i] += 1;
while i > 0 && indices[i] > max_indices0 + i {
i -= 1;
indices[i] += 1;
}
if indices[0] > max_indices0 {
break;
}
combination[i] = values[indices[i]].clone();
for i in i + 1..r {
indices[i] = indices[i - 1] + 1;
combination[i] = values[indices[i]].clone();
}
}
}
#[inline]
pub fn each_combination_ref<'v, T, F>(values: &'v [T], r: usize, fun: F) -> ()
where
F: FnMut(&[&'v T]) -> (),
{
let v: Vec<&T> = values.iter().map(|elt| elt).collect();
each_combination(&v, r, fun);
}
#[cfg(test)]
mod tests {
#[test]
fn test_zero() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 0, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v.is_empty());
}
#[test]
fn test_one() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 1, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v == [[1], [2], [3], [4]]);
}
#[test]
fn test_two() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 2, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v == [[1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4]]);
}
#[test]
fn test_three() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 3, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v == [[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]);
}
#[test]
fn test_four() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 4, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v == [[1, 2, 3, 4]]);
}
#[test]
fn test_five() {
let values = [1, 2, 3, 4];
let mut v: Vec<Vec<i32>> = Vec::new();
super::each_combination(&values, 5, |p| {
v.push(p.iter().cloned().collect());
});
assert!(v.is_empty());
}
}