Moved nth_lex out of struct impl
This commit is contained in:
		@@ -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)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub struct Combinator<T: Clone + Ord> {
 | 
					pub struct Combinator<T: Clone + Ord> {
 | 
				
			||||||
    pub current: Vec<T>,
 | 
					    pub current: Vec<T>,
 | 
				
			||||||
@@ -34,37 +69,6 @@ impl<T: Clone + Ord> Combinator<T> {
 | 
				
			|||||||
            idx: 0,
 | 
					            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> {
 | 
					impl<T: Clone + Ord> Iterator for Combinator<T> {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,54 +8,54 @@ fn factorial(num: usize) -> usize {
 | 
				
			|||||||
    fact
 | 
					    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)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
pub struct Permutator<T: Copy + Ord> {
 | 
					pub struct Permutator<T: Clone + Ord> {
 | 
				
			||||||
    pub current: Vec<T>,
 | 
					    pub current: Vec<T>,
 | 
				
			||||||
    idx: usize,
 | 
					    idx: usize,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl<T: Copy + 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 {
 | 
				
			||||||
            current: elements,
 | 
					            current: elements,
 | 
				
			||||||
            idx: 0,
 | 
					            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>;
 | 
					    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
 | 
				
			||||||
@@ -73,7 +73,7 @@ impl<T: Copy + Ord> Iterator for Permutator<T> {
 | 
				
			|||||||
        for idx in 1..=digits.len() {
 | 
					        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]);
 | 
					            perm.push(digits[permutations].clone());
 | 
				
			||||||
            digits.remove(permutations);
 | 
					            digits.remove(permutations);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        self.idx += 1;
 | 
					        self.idx += 1;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user