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)]
pub struct Permutator<T: Clone + Ord> {
pub current: Vec<T>,
pub elements: Vec<T>,
idx: usize,
}
impl<T: Clone + Ord> Permutator<T> {
pub fn new(elements: Vec<T>) -> Self {
Self {
current: elements,
idx: 0,
}
Self { 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>;
/// Returns the next permutation and changes the current permutation to it
/// This operation wraps around
fn next(&mut self) -> Option<Self::Item> {
if self.current.is_empty() {
if self.elements.is_empty() {
return None;
}
let mut digits = self.current.clone();
if self.idx == factorial(digits.len()) {
if self.idx == 0 {
self.idx += 1;
return Some(self.elements.clone());
}
let num_unique_digits = self.elements.len();
if self.idx == factorial(num_unique_digits) {
return None;
}
let mut digits = self.elements.clone();
let mut perm = Vec::new();
let num_unique_digits = digits.len();
let mut remainder = 1;
for idx in 1..=digits.len() {
let mut remainder = self.idx;
for idx in 1..=num_unique_digits {
let permutations = remainder / factorial(num_unique_digits - idx);
remainder %= factorial(num_unique_digits - idx);
perm.push(digits[permutations].clone());
digits.remove(permutations);
perm.push(digits.remove(permutations));
}
self.idx += 1;
self.current = digits;
Some(self.current.clone())
Some(perm)
}
}
#[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);
}
}