pub struct Permutator<'a, T: 'a + ?Sized> {
indexes: IndexCounters,
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 {
indexes: IndexCounters {
indexes: vec![0; nlists],
max: nvalues,
curr_iter: 0,
max_iters: max_iters,
},
lists: lists,
nlists: nlists,
single_list: single_list
}
}
pub fn set_index(&mut self, iter_no: usize, indexes: Vec<usize>) {
debug_assert!(indexes.len() == self.indexes.max.len(), "indexes have an invalid length");
self.indexes.indexes = indexes;
self.indexes.curr_iter = iter_no;
}
pub fn get_index(&self) -> (usize, Vec<usize>) {
(self.indexes.curr_iter, self.indexes.indexes.clone())
}
pub fn max_permutations(&self) -> usize {
self.indexes.max_iters
}
pub fn reset(&mut self) {
self.indexes.reset();
self.indexes.curr_iter = 0;
}
pub fn next_with_buffer(&mut self, buffer: &mut [&'a T]) -> bool {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return false
}
}
debug_assert!(buffer.len() >= self.nlists, "buffer is not large enough to contain the permutation");
self.indexes.curr_iter += 1;
let mut index = 0;
unsafe {
if self.single_list {
for value in self.indexes.indexes.iter().map(|v| *self.lists.get_unchecked(0).get_unchecked(*v)) {
*buffer.get_unchecked_mut(index) = value;
index += 1;
}
} else {
for value in self.indexes.indexes.iter().enumerate()
.map(|(list, value)| *self.lists.get_unchecked(list).get_unchecked(*value))
{
*buffer.get_unchecked_mut(index) = value;
index += 1;
}
};
}
self.indexes.increment(&self.nlists - 1);
true
}
}
impl<'a, T: 'a + ?Sized> Iterator for Permutator<'a, T> {
type Item = Vec<&'a T>;
fn nth(&mut self, mut n: usize) -> Option<Vec<&'a T>> {
loop {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return None
}
}
self.indexes.curr_iter += 1;
if n == 0 {
let output = if self.single_list {
self.indexes.indexes.iter()
.map(|value| unsafe {
*self.lists.get_unchecked(0).get_unchecked(*value)
})
.collect::<Vec<&T>>()
} else {
self.indexes.indexes.iter().enumerate()
.map(|(list, value)| unsafe {
*self.lists.get_unchecked(list).get_unchecked(*value)
})
.collect::<Vec<&T>>()
};
self.indexes.increment(&self.nlists - 1);
return Some(output)
}
self.indexes.increment(&self.nlists - 1);
n -= 1;
}
}
fn next(&mut self) -> Option<Vec<&'a T>> {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return None
}
}
self.indexes.curr_iter += 1;
let output = if self.single_list {
self.indexes.indexes.iter()
.map(|value| unsafe {
*self.lists.get_unchecked(0).get_unchecked(*value)
})
.collect::<Vec<&T>>()
} else {
self.indexes.indexes.iter().enumerate()
.map(|(list, value)| unsafe {
*self.lists.get_unchecked(list).get_unchecked(*value)
})
.collect::<Vec<&T>>()
};
self.indexes.increment(&self.nlists - 1);
Some(output)
}
}
pub struct ValuePermutator<'a, T: 'a + Copy> {
indexes: IndexCounters,
lists: &'a [&'a [T]],
nlists: usize,
single_list: bool
}
impl<'a, T: Copy> ValuePermutator<'a, T> {
pub fn new(lists: &'a [&'a [T]]) -> ValuePermutator<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();
ValuePermutator {
indexes: IndexCounters {
indexes: vec![0; nlists],
max: nvalues,
curr_iter: 0,
max_iters: max_iters,
},
lists: lists,
nlists: nlists,
single_list: single_list
}
}
pub fn set_index(&mut self, iter_no: usize, indexes: Vec<usize>) {
debug_assert!(indexes.len() == self.indexes.max.len(), "indexes have an invalid length");
self.indexes.indexes = indexes;
self.indexes.curr_iter = iter_no;
}
pub fn get_index(&self) -> (usize, Vec<usize>) {
(self.indexes.curr_iter, self.indexes.indexes.clone())
}
pub fn max_permutations(&self) -> usize {
self.indexes.max_iters
}
pub fn reset(&mut self) {
self.indexes.reset();
self.indexes.curr_iter = 0;
}
pub fn next_with_buffer(&mut self, buffer: &mut [T]) -> bool {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return false
}
}
debug_assert!(buffer.len() >= self.nlists, "buffer is not large enough to contain the permutation");
self.indexes.curr_iter += 1;
let mut index = 0;
unsafe {
if self.single_list {
for value in self.indexes.indexes.iter().map(|v| *self.lists.get_unchecked(0).get_unchecked(*v)) {
*buffer.get_unchecked_mut(index) = value;
index += 1;
}
} else {
for value in self.indexes.indexes.iter().enumerate()
.map(|(list, value)| *self.lists.get_unchecked(list).get_unchecked(*value))
{
*buffer.get_unchecked_mut(index) = value;
index += 1;
}
};
}
self.indexes.increment(&self.nlists - 1);
true
}
}
impl<'a, T: Copy> Iterator for ValuePermutator<'a, T> {
type Item = Vec<T>;
fn nth(&mut self, mut n: usize) -> Option<Vec<T>> {
loop {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return None
}
}
self.indexes.curr_iter += 1;
if n == 0 {
let output = if self.single_list {
self.indexes.indexes.iter()
.map(|value| unsafe {
*self.lists.get_unchecked(0).get_unchecked(*value)
})
.collect::<Vec<T>>()
} else {
self.indexes.indexes.iter().enumerate()
.map(|(list, value)| unsafe {
*self.lists.get_unchecked(list).get_unchecked(*value)
})
.collect::<Vec<T>>()
};
self.indexes.increment(&self.nlists - 1);
return Some(output)
}
self.indexes.increment(&self.nlists - 1);
n -= 1;
}
}
fn next(&mut self) -> Option<Vec<T>> {
if self.indexes.max_iters != 0 {
if self.indexes.curr_iter == self.indexes.max_iters {
return None
}
}
self.indexes.curr_iter += 1;
let output = if self.single_list {
self.indexes.indexes.iter()
.map(|value| unsafe {
*self.lists.get_unchecked(0).get_unchecked(*value)
})
.collect::<Vec<T>>()
} else {
self.indexes.indexes.iter().enumerate()
.map(|(list, value)| unsafe {
*self.lists.get_unchecked(list).get_unchecked(*value)
})
.collect::<Vec<T>>()
};
self.indexes.increment(&self.nlists - 1);
Some(output)
}
}
#[derive(Clone, Debug)]
pub struct IndexCounters {
indexes: Vec<usize>,
max: Vec<usize>,
curr_iter: usize,
max_iters: usize,
}
impl IndexCounters {
fn increment(&mut self, mut nlists: usize) {
loop {
let mut increment = false;
{
let current = unsafe { self.indexes.get_unchecked_mut(nlists) };
let max = unsafe { self.max.get_unchecked(nlists) };
if *current == *max {
if nlists != 0 {
*current = 0;
increment = true;
}
} else {
*current += 1;
}
}
if increment {
nlists -= 1;
} else {
break
}
}
}
fn reset(&mut self) {
for value in self.indexes.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);
}
let mut permutator = Permutator::new(&inputs[..]);
let mut expected = expected[..].iter();
assert_eq!(&(permutator.nth(10).unwrap()), expected.nth(10).unwrap());
assert_eq!(&(permutator.nth(0).unwrap()), expected.nth(0).unwrap());
}
#[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);
}
}
}