How do I find the number of permutations or combinations in rust?
E.g. C(10,6) = 210
I can't find this function in the standard library, nor can I find the factorial operator there (which would suffice).
How do I find the number of permutations or combinations in rust?
E.g. C(10,6) = 210
I can't find this function in the standard library, nor can I find the factorial operator there (which would suffice).
Building off @vallentin's answer, there are many optimizations that could be made. Let's use the same factorial function (for now):
fn factorial(n: u64) -> u64 {
(1..=n).product()
}
For count_permutations, n! / (n - r)! is actually just the product of all numbers between n - r + 1 and n (inclusive), so we don't even need to compute 2 factorials (which could overflow and involve computing the product of overlapping numbers):
fn count_permutations(n: u64, r: u64) -> u64 {
(n - r + 1..=n).product()
}
We can do a similar optimization for count_combinations:
fn count_combinations(n: u64, r: u64) -> u64 {
(n - r + 1..=n).product::<u64>() / factorial(r)
}
count_permutations is pretty much completely optimized, being both fast and correct (if the result of count_permutations can fit in a u64 then it should never overflow).
count_combinations still has a couple flaws, namely that since it's computing a product then dividing, its result could fit in a u64, but the function will still overflow. You can make it pretty close to non-overflowing with alternating multiplication and division:
fn count_combinations(n: u64, r: u64) -> u64 {
if r > n {
0
} else {
(1..=r).fold(1, |acc, val| acc * (n - val + 1) / val)
}
}
Putting it all together:
fn count_combinations(n: u64, r: u64) -> u64 {
if r > n {
0
} else {
(1..=r).fold(1, |acc, val| acc * (n - val + 1) / val)
}
}
fn count_permutations(n: u64, r: u64) -> u64 {
(n - r + 1..=n).product()
}
fn main() {
println!("{}", count_combinations(10, 6));
println!("{}", count_permutations(10, 6));
}
Note that there are some micro-optimizations that you can do, namely going to r.min(n - r) instead of r for count_combinations, since count_combinations(n, r) == count_combinations(n, n - r), and going to the smaller of the two will shrink the loop size:
fn count_combinations(n: u64, r: u64) -> u64 {
if r > n {
0
} else {
(1..=r.min(n - r)).fold(1, |acc, val| acc * (n - val + 1) / val)
}
}
The standard library doesn't include any operator or function for calculating the factorial of a number.
Instead you can use the factorial crate or you could use the num crate, which the Rust Cookbook includes an example of. Here's a variation of the Rust Cookbook example, without using the num crate.
fn factorial(n: u64) -> u64 {
let mut f = 1;
for i in 1..=n {
f *= i;
}
f
}
As already commented by L. F., this could be expressed shorter using product(), which the documentation for product() includes an example of.
fn factorial(n: u64) -> u64 {
(1..=n).product()
}
The standard library also doesn't have functions for calculating the number of permutations or combinations a given n and r would give. Instead you can just translate the formulas into functions, like this:
/// n! / (r! * (n - r)!)
fn count_combinations(n: u64, r: u64) -> u64 {
factorial(n) / (factorial(r) * factorial(n - r))
}
/// n! / (n - r)!
fn count_permutations(n: u64, r: u64) -> u64 {
factorial(n) / factorial(n - r)
}
fn main() {
println!("{}", count_combinations(10, 6)); // Prints `210`
println!("{}", count_permutations(10, 6)); // Prints `151200`
}
If you actually want to produce permutations and/or combinations, then you could use the itertools crate and specifically use the permutations() and combinations() functions.