extern crate num;
use self::num::*;
pub fn product<T>(start: T, end: T) -> T
where
T: PrimInt,
{
assert!(start <= end + T::one());
let mut res = T::one();
for x in range(start, end + T::one()) {
res = res * x;
}
res
}
pub fn factorial<T>(n: T) -> T
where
T: PrimInt,
{
product(T::one(), n)
}
pub fn binomial<T>(k: T, n: T) -> T
where
T: PrimInt,
{
if k < T::zero() || k > n {
return T::zero();
}
product(n - k + T::one(), n) / factorial(k)
}
pub fn pre_image(n: usize, t: &[usize]) -> Vec<Vec<usize>> {
let mut res = vec![Vec::new(); n];
for (i, &v) in t.iter().enumerate() {
res[v].push(i);
}
res
}
pub fn invert(t: &[usize]) -> Vec<usize> {
let n = t.len();
let mut res = vec![n; n];
for (i, &v) in t.iter().enumerate() {
debug_assert_eq!(res[v], n); res[v] = i;
}
res
}
pub fn permutation_of_injection(n: usize, t: &[usize]) -> Vec<usize> {
let mut res = t.to_vec();
let mut unassigned = vec![true; n];
for &v in t {
unassigned[v] = false;
}
for (i, &b) in unassigned.iter().enumerate() {
if b {
res.push(i);
}
}
res
}
pub fn compose(p: &[usize], q: &[usize]) -> Vec<usize> {
debug_assert_eq!(p.len(), q.len());
q.iter().map(|&x| p[x]).collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn unit_product() {
assert_eq!(120, product(4, 6));
assert_eq!(17, product(17, 17));
assert_eq!(1, product(8, 7));
}
#[test]
fn unit_factorial() {
assert_eq!(1, factorial(0));
assert_eq!(120, factorial(5));
}
#[test]
fn unit_binomial() {
assert_eq!(35, binomial(3, 7));
assert_eq!(10, binomial(2, 5));
assert_eq!(42, binomial(1, 42));
assert_eq!(0, binomial(5, 4));
assert_eq!(0, binomial(-1, 4));
}
#[test]
fn unit_invert() {
assert_eq!(invert(&[4, 0, 1, 3, 2]), [1, 2, 4, 3, 0]);
}
#[test]
fn unit_permutation_of_injection() {
assert_eq!(permutation_of_injection(6, &[2, 0, 5]), [2, 0, 5, 1, 3, 4]);
}
}