pub struct Permutator<'a, T: 'a + ?Sized> {
counter: Counter,
curr_iteration: usize,
max_iterations: usize,
lists: &'a [&'a [&'a T]],
nlists: usize,
single_list: bool
}
impl<'a, T: 'a + ?Sized> Permutator<'a, T> {
pub fn new(lists: &'a [&'a [&'a T]]) -> Permutator<T> {
let mut nlists = lists.len();
let single_list = nlists == 1;
let nvalues = if single_list {
nlists = lists[0].len();
(0..nlists).map(|_| nlists - 1).collect::<Vec<usize>>()
} else {
lists.iter().map(|list| list.len() - 1).collect::<Vec<usize>>()
};
let max_iters = nvalues.iter().map(|x| x + 1).product();
Permutator {
counter: Counter {
counter: vec![0; nlists],
max: nvalues,
},
curr_iteration: 0,
lists: lists,
max_iterations: max_iters,
nlists: nlists,
single_list: single_list
}
}
pub fn reset(&mut self) {
self.counter.reset();
self.curr_iteration = 0;
}
}
impl<'a, T: 'a + ?Sized> Iterator for Permutator<'a, T> {
type Item = Vec<&'a T>;
fn next(&mut self) -> Option<Vec<&'a T>> {
if self.curr_iteration == self.max_iterations {
return None
}
self.curr_iteration += 1;
let output = if self.single_list {
self.counter.counter.iter()
.map(|value| self.lists[0][*value])
.collect::<Vec<&T>>()
} else {
self.counter.counter.iter().enumerate()
.map(|(list, value)| self.lists[list][*value])
.collect::<Vec<&T>>()
};
self.counter.increment(&self.nlists - 1);
Some(output)
}
}
struct Counter {
counter: Vec<usize>,
max: Vec<usize>
}
impl Counter {
fn increment(&mut self, nlists: usize) {
if self.counter[nlists] == self.max[nlists] {
if nlists != 0 {
self.counter[nlists] = 0;
self.increment(nlists - 1);
}
} else {
self.counter[nlists] += 1;
}
}
fn reset(&mut self) {
for value in self.counter.iter_mut() { *value = 0; }
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_million_permutations() {
let inputs = [
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..],
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..],
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..],
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..],
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..],
&["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"][..]
];
assert_eq!(1_000_000, Permutator::new(&inputs[..]).count())
}
#[test]
fn test_permutation_values() {
let inputs = [&["1", "2", "3"][..], &["1", "2", "3"][..], &["1", "2", "3"][..]];
let expected = [
&["1", "1", "1"][..], &["1", "1", "2"][..], &["1", "1", "3"][..],
&["1", "2", "1"][..], &["1", "2", "2"][..], &["1", "2", "3"][..],
&["1", "3", "1"][..], &["1", "3", "2"][..], &["1", "3", "3"][..],
&["2", "1", "1"][..], &["2", "1", "2"][..], &["2", "1", "3"][..],
&["2", "2", "1"][..], &["2", "2", "2"][..], &["2", "2", "3"][..],
&["2", "3", "1"][..], &["2", "3", "2"][..], &["2", "3", "3"][..],
&["3", "1", "1"][..], &["3", "1", "2"][..], &["3", "1", "3"][..],
&["3", "2", "1"][..], &["3", "2", "2"][..], &["3", "2", "3"][..],
&["3", "3", "1"][..], &["3", "3", "2"][..], &["3", "3", "3"][..],
];
for (output, expected) in Permutator::new(&inputs[..]).zip(expected[..].iter()) {
assert_eq!(&output, expected);
}
}
#[test]
fn single_list_permutation() {
let input = [&["1", "2", "3"][..]];
let expected = [
&["1", "1", "1"][..], &["1", "1", "2"][..], &["1", "1", "3"][..],
&["1", "2", "1"][..], &["1", "2", "2"][..], &["1", "2", "3"][..],
&["1", "3", "1"][..], &["1", "3", "2"][..], &["1", "3", "3"][..],
&["2", "1", "1"][..], &["2", "1", "2"][..], &["2", "1", "3"][..],
&["2", "2", "1"][..], &["2", "2", "2"][..], &["2", "2", "3"][..],
&["2", "3", "1"][..], &["2", "3", "2"][..], &["2", "3", "3"][..],
&["3", "1", "1"][..], &["3", "1", "2"][..], &["3", "1", "3"][..],
&["3", "2", "1"][..], &["3", "2", "2"][..], &["3", "2", "3"][..],
&["3", "3", "1"][..], &["3", "3", "2"][..], &["3", "3", "3"][..],
];
for (output, expected) in Permutator::new(&input[..]).zip(expected[..].iter()) {
assert_eq!(&output, expected);
}
}
#[test]
fn test_reset() {
let input = [&["1", "2", "3"][..]];
let expected = [
&["1", "1", "1"][..], &["1", "1", "2"][..], &["1", "1", "3"][..],
&["1", "2", "1"][..], &["1", "2", "2"][..], &["1", "2", "3"][..],
&["1", "3", "1"][..], &["1", "3", "2"][..], &["1", "3", "3"][..],
&["2", "1", "1"][..], &["2", "1", "2"][..], &["2", "1", "3"][..],
&["2", "2", "1"][..], &["2", "2", "2"][..], &["2", "2", "3"][..],
&["2", "3", "1"][..], &["2", "3", "2"][..], &["2", "3", "3"][..],
&["3", "1", "1"][..], &["3", "1", "2"][..], &["3", "1", "3"][..],
&["3", "2", "1"][..], &["3", "2", "2"][..], &["3", "2", "3"][..],
&["3", "3", "1"][..], &["3", "3", "2"][..], &["3", "3", "3"][..],
];
let mut permutator = Permutator::new(&input[..]);
for (output, expected) in permutator.by_ref().zip(expected[..].iter()) {
assert_eq!(&output, expected);
}
permutator.reset();
for (output, expected) in permutator.zip(expected[..].iter()) {
assert_eq!(&output, expected);
}
}
}