Moved nth_lex out of struct impl
This commit is contained in:
parent
d3a93a875f
commit
fdf46c9dd3
@ -16,6 +16,41 @@ fn binomial(n: usize, k: usize) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn nth_lex<T: Clone + Ord>(
|
||||
mut elements: Vec<T>,
|
||||
k: usize,
|
||||
nth: usize,
|
||||
) -> Result<Vec<T>, Box<dyn Error>> {
|
||||
elements.sort();
|
||||
let num_elements = elements.len();
|
||||
let num_combinations = binomial(num_elements, k);
|
||||
if nth > num_combinations || k > num_elements || nth == 0 || k == 0 {
|
||||
return Err(Box::from("Out of bounds"));
|
||||
}
|
||||
let mut i = 0;
|
||||
let mut remaining_k = k;
|
||||
let mut comb = Vec::new();
|
||||
let mut remainder = nth - 1;
|
||||
while remaining_k > 0 {
|
||||
// Count the number of combinations that start with elements[i]
|
||||
// example with n = 5, k = 2
|
||||
// nth <= 4 select first
|
||||
// nth <= 7 select second
|
||||
// nth <= 9 select third
|
||||
// nth == 10 select fourth
|
||||
let count = binomial(num_elements - i - 1, remaining_k - 1);
|
||||
if remainder < count {
|
||||
// If the nth combination is within the count, pick this element
|
||||
comb.push(elements[i].clone());
|
||||
remaining_k -= 1;
|
||||
} else {
|
||||
remainder -= count;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
Ok(comb)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Combinator<T: Clone + Ord> {
|
||||
pub current: Vec<T>,
|
||||
@ -34,37 +69,6 @@ impl<T: Clone + Ord> Combinator<T> {
|
||||
idx: 0,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn nth_lex(mut elements: Vec<T>, k: usize, nth: usize) -> Result<Vec<T>, Box<dyn Error>> {
|
||||
elements.sort();
|
||||
let num_elements = elements.len();
|
||||
let num_combinations = binomial(num_elements, k);
|
||||
if nth > num_combinations || k > num_elements || nth == 0 || k == 0 {
|
||||
return Err(Box::from("Out of bounds"));
|
||||
}
|
||||
let mut i = 0;
|
||||
let mut remaining_k = k;
|
||||
let mut comb = Vec::new();
|
||||
let mut remainder = nth - 1;
|
||||
while remaining_k > 0 {
|
||||
// Count the number of combinations that start with elements[i]
|
||||
// example with n = 5, k = 2
|
||||
// nth <= 4 select first
|
||||
// nth <= 7 select second
|
||||
// nth <= 9 select third
|
||||
// nth == 10 select fourth
|
||||
let count = binomial(num_elements - i - 1, remaining_k - 1);
|
||||
if remainder < count {
|
||||
// If the nth combination is within the count, pick this element
|
||||
comb.push(elements[i].clone());
|
||||
remaining_k -= 1;
|
||||
} else {
|
||||
remainder -= count;
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
Ok(comb)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Clone + Ord> Iterator for Combinator<T> {
|
||||
|
@ -8,54 +8,54 @@ fn factorial(num: usize) -> usize {
|
||||
fact
|
||||
}
|
||||
|
||||
/// 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<T: Clone + Ord>(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].clone());
|
||||
digits.remove(permutations);
|
||||
}
|
||||
Ok(perm)
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Permutator<T: Copy + Ord> {
|
||||
pub struct Permutator<T: Clone + Ord> {
|
||||
pub current: Vec<T>,
|
||||
idx: usize,
|
||||
}
|
||||
|
||||
impl<T: Copy + Ord> Permutator<T> {
|
||||
impl<T: Clone + 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> {
|
||||
impl<T: Clone + Ord> Iterator for Permutator<T> {
|
||||
type Item = Vec<T>;
|
||||
/// Returns the next permutation and changes the current permutation to it
|
||||
/// This operation wraps around
|
||||
@ -73,7 +73,7 @@ impl<T: Copy + Ord> Iterator for Permutator<T> {
|
||||
for idx in 1..=digits.len() {
|
||||
let permutations = remainder / factorial(num_unique_digits - idx);
|
||||
remainder %= factorial(num_unique_digits - idx);
|
||||
perm.push(digits[permutations]);
|
||||
perm.push(digits[permutations].clone());
|
||||
digits.remove(permutations);
|
||||
}
|
||||
self.idx += 1;
|
||||
|
Loading…
Reference in New Issue
Block a user