84 lines
2.5 KiB
Rust
84 lines
2.5 KiB
Rust
use std::error::Error;
|
|
|
|
fn factorial(num: usize) -> usize {
|
|
let mut fact = 1;
|
|
for n in 1..=num {
|
|
fact *= n;
|
|
}
|
|
fact
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct Permutator<T: Copy + Ord> {
|
|
pub current: Vec<T>,
|
|
idx: usize,
|
|
}
|
|
|
|
impl<T: Copy + Ord> Permutator<T> {
|
|
pub fn new(elements: Vec<T>) -> Self {
|
|
Self {
|
|
current: elements,
|
|
idx: 0,
|
|
}
|
|
}
|
|
|
|
/// Explanation
|
|
///
|
|
/// there are 10! possible permutations
|
|
/// for each first number there are 9!, for each first 2 numbers 8!, etc.
|
|
/// we check how many times we have 9! permutations before we're over 1_000_000
|
|
/// aka. 1000000 / 9!
|
|
/// we take the remainder and check how many times we have 8! before we?re over it
|
|
/// (1000000 % 9!) 8!
|
|
/// etc.
|
|
/// every iteration we remove the digit by the idx from the original permutation
|
|
/// we only check for 999999 permutations because we already have the first one
|
|
///
|
|
pub fn nth_lex(mut digits: Vec<T>, nth: usize) -> Result<Vec<T>, Box<dyn Error>> {
|
|
digits.sort();
|
|
if nth == 1 {
|
|
return Ok(digits);
|
|
}
|
|
if nth > factorial(digits.len()) || nth == 0 {
|
|
return Err(Box::from("Out of bounds"));
|
|
}
|
|
let mut perm = Vec::new();
|
|
let num_unique_digits = digits.len();
|
|
let mut remainder = nth - 1;
|
|
for idx in 1..=digits.len() {
|
|
let permutations = remainder / factorial(num_unique_digits - idx);
|
|
remainder %= factorial(num_unique_digits - idx);
|
|
perm.push(digits[permutations]);
|
|
digits.remove(permutations);
|
|
}
|
|
Ok(perm)
|
|
}
|
|
}
|
|
|
|
impl<T: Copy + Ord> 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() {
|
|
return None;
|
|
}
|
|
let mut digits = self.current.clone();
|
|
if self.idx == factorial(digits.len()) {
|
|
return None;
|
|
}
|
|
let mut perm = Vec::new();
|
|
let num_unique_digits = digits.len();
|
|
let mut remainder = 1;
|
|
for idx in 1..=digits.len() {
|
|
let permutations = remainder / factorial(num_unique_digits - idx);
|
|
remainder %= factorial(num_unique_digits - idx);
|
|
perm.push(digits[permutations]);
|
|
digits.remove(permutations);
|
|
}
|
|
self.idx += 1;
|
|
self.current = digits;
|
|
Some(self.current.clone())
|
|
}
|
|
}
|