Add test for permutation and fixed it
This commit is contained in:
parent
cc626a6d85
commit
e293fb90d3
@ -42,42 +42,82 @@ pub fn nth_lex<T: Clone + Ord>(mut digits: Vec<T>, nth: usize) -> Result<Vec<T>,
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Permutator<T: Clone + Ord> {
|
pub struct Permutator<T: Clone + Ord> {
|
||||||
pub current: Vec<T>,
|
pub elements: Vec<T>,
|
||||||
idx: usize,
|
idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + Ord> Permutator<T> {
|
impl<T: Clone + Ord> Permutator<T> {
|
||||||
pub fn new(elements: Vec<T>) -> Self {
|
pub fn new(elements: Vec<T>) -> Self {
|
||||||
Self {
|
Self { elements, idx: 0 }
|
||||||
current: elements,
|
|
||||||
idx: 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Clone + Ord> Iterator for Permutator<T> {
|
impl<T: Clone + Ord + std::fmt::Display> Iterator for Permutator<T> {
|
||||||
type Item = Vec<T>;
|
type Item = Vec<T>;
|
||||||
/// Returns the next permutation and changes the current permutation to it
|
/// Returns the next permutation and changes the current permutation to it
|
||||||
/// This operation wraps around
|
/// This operation wraps around
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
if self.current.is_empty() {
|
if self.elements.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let mut digits = self.current.clone();
|
if self.idx == 0 {
|
||||||
if self.idx == factorial(digits.len()) {
|
self.idx += 1;
|
||||||
|
return Some(self.elements.clone());
|
||||||
|
}
|
||||||
|
let num_unique_digits = self.elements.len();
|
||||||
|
if self.idx == factorial(num_unique_digits) {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
let mut digits = self.elements.clone();
|
||||||
let mut perm = Vec::new();
|
let mut perm = Vec::new();
|
||||||
let num_unique_digits = digits.len();
|
let mut remainder = self.idx;
|
||||||
let mut remainder = 1;
|
for idx in 1..=num_unique_digits {
|
||||||
for idx in 1..=digits.len() {
|
|
||||||
let permutations = remainder / factorial(num_unique_digits - idx);
|
let permutations = remainder / factorial(num_unique_digits - idx);
|
||||||
remainder %= factorial(num_unique_digits - idx);
|
remainder %= factorial(num_unique_digits - idx);
|
||||||
perm.push(digits[permutations].clone());
|
perm.push(digits.remove(permutations));
|
||||||
digits.remove(permutations);
|
|
||||||
}
|
}
|
||||||
self.idx += 1;
|
self.idx += 1;
|
||||||
self.current = digits;
|
Some(perm)
|
||||||
Some(self.current.clone())
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::permutation::{nth_lex, Permutator};
|
||||||
|
|
||||||
|
const SMALL: [i8; 3] = [1, 2, 3];
|
||||||
|
|
||||||
|
// Nth Lex
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nth_lex_zero_small() {
|
||||||
|
let small = SMALL.to_vec();
|
||||||
|
assert!(nth_lex(small, 0).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn nth_lex_small() {
|
||||||
|
let small = SMALL.to_vec();
|
||||||
|
assert_eq!(nth_lex(small.clone(), 1).unwrap(), vec![1, 2, 3]);
|
||||||
|
assert_eq!(nth_lex(small.clone(), 2).unwrap(), vec![1, 3, 2]);
|
||||||
|
assert_eq!(nth_lex(small.clone(), 3).unwrap(), vec![2, 1, 3]);
|
||||||
|
assert_eq!(nth_lex(small.clone(), 4).unwrap(), vec![2, 3, 1]);
|
||||||
|
assert_eq!(nth_lex(small.clone(), 5).unwrap(), vec![3, 1, 2]);
|
||||||
|
assert_eq!(nth_lex(small.clone(), 6).unwrap(), vec![3, 2, 1]);
|
||||||
|
assert!(nth_lex(small.clone(), 7).is_err());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permutator
|
||||||
|
#[test]
|
||||||
|
fn perm_small() {
|
||||||
|
let small = SMALL.to_vec();
|
||||||
|
let mut comb = Permutator::new(small);
|
||||||
|
assert_eq!(comb.next(), Some(vec![1, 2, 3]));
|
||||||
|
assert_eq!(comb.next(), Some(vec![1, 3, 2]));
|
||||||
|
assert_eq!(comb.next(), Some(vec![2, 1, 3]));
|
||||||
|
assert_eq!(comb.next(), Some(vec![2, 3, 1]));
|
||||||
|
assert_eq!(comb.next(), Some(vec![3, 1, 2]));
|
||||||
|
assert_eq!(comb.next(), Some(vec![3, 2, 1]));
|
||||||
|
assert_eq!(comb.next(), None);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user