use crate::Permutation;
#[derive(Clone, Debug)]
pub struct Permutations {
n: usize,
len: usize,
}
impl Permutations {
pub fn new(n: usize) -> Permutations {
let len = (2..=n).product::<usize>();
Permutations { n, len }
}
pub fn get(&self, index: usize) -> Option<Permutation> {
if index < self.len {
let mut v = Vec::new();
let mut es = (0..self.n).collect::<Vec<_>>();
let mut divisor = self.len;
let mut k = self.n;
let mut i = index;
while k > 0 {
divisor /= k;
let j = i / divisor;
v.push(es.remove(j));
i %= divisor;
k -= 1;
}
Some(Permutation::try_from(v).unwrap())
} else {
None
}
}
#[allow(clippy::len_without_is_empty)]
pub fn len(&self) -> usize {
self.len
}
pub fn iter(&self) -> Iter {
Iter::new(self.clone())
}
}
impl IntoIterator for Permutations {
type Item = Permutation;
type IntoIter = Iter;
fn into_iter(self) -> Iter {
Iter::new(self)
}
}
impl<'a> IntoIterator for &'a Permutations {
type Item = Permutation;
type IntoIter = Iter;
fn into_iter(self) -> Iter {
self.iter()
}
}
#[derive(Clone, Debug)]
pub struct Iter {
permutations: Permutations,
next_index: usize,
}
impl Iter {
fn new(permutations: Permutations) -> Iter {
let next_index = 0;
Iter {
permutations,
next_index,
}
}
}
impl Iterator for Iter {
type Item = Permutation;
fn next(&mut self) -> Option<Permutation> {
if let Some(result) = self.permutations.get(self.next_index) {
self.next_index += 1;
Some(result)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
let len = self.permutations.len() - self.next_index;
(len, Some(len))
}
}
impl ExactSizeIterator for Iter {}
#[cfg(test)]
mod tests {
use crate::Permutation;
use crate::Permutations;
#[test]
fn test_len_0() {
let ps = Permutations::new(0);
assert_eq!(1, ps.len());
}
#[test]
fn test_len_1() {
let ps = Permutations::new(1);
assert_eq!(1, ps.len());
}
#[test]
fn test_len_2() {
let ps = Permutations::new(2);
assert_eq!(2, ps.len());
}
#[test]
fn test_len_3() {
let ps = Permutations::new(3);
assert_eq!(6, ps.len());
}
#[test]
fn test_get() {
let ps = Permutations::new(3);
assert_eq!(Some(Permutation::try_from(&[0, 1, 2]).unwrap()), ps.get(0));
assert_eq!(Some(Permutation::try_from(&[0, 2, 1]).unwrap()), ps.get(1));
assert_eq!(Some(Permutation::try_from(&[1, 0, 2]).unwrap()), ps.get(2));
assert_eq!(Some(Permutation::try_from(&[1, 2, 0]).unwrap()), ps.get(3));
assert_eq!(Some(Permutation::try_from(&[2, 0, 1]).unwrap()), ps.get(4));
assert_eq!(Some(Permutation::try_from(&[2, 1, 0]).unwrap()), ps.get(5));
assert_eq!(None, ps.get(6));
}
#[test]
fn test_iter() {
let ps = Permutations::new(3);
let mut iter = ps.iter();
assert_eq!(
Some(Permutation::try_from(&[0, 1, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[0, 2, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 0, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 2, 0]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 0, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 1, 0]).unwrap()),
iter.next()
);
assert_eq!(None, iter.next());
}
#[test]
fn test_into_iter_owned() {
let ps = Permutations::new(3);
let mut iter = ps.into_iter();
assert_eq!(
Some(Permutation::try_from(&[0, 1, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[0, 2, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 0, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 2, 0]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 0, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 1, 0]).unwrap()),
iter.next()
);
assert_eq!(None, iter.next());
}
#[test]
fn test_into_iter_ref() {
let ps = &Permutations::new(3);
let mut iter = ps.into_iter();
assert_eq!(
Some(Permutation::try_from(&[0, 1, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[0, 2, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 0, 2]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[1, 2, 0]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 0, 1]).unwrap()),
iter.next()
);
assert_eq!(
Some(Permutation::try_from(&[2, 1, 0]).unwrap()),
iter.next()
);
assert_eq!(None, iter.next());
}
#[test]
fn test_iter_exact_size_iterator_len() {
let ps = &Permutations::new(3);
let mut iter = ps.into_iter();
assert_eq!(6, iter.len());
iter.next();
assert_eq!(5, iter.len());
}
}