Add test for permutation and fixed it

This commit is contained in:
Fabian Schmidt 2024-11-28 12:32:34 +01:00
parent cc626a6d85
commit e293fb90d3

View File

@ -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);
} }
} }