euler/rust/src/euler/prime.rs

73 lines
1.5 KiB
Rust

fn subfactors(mut n: u64, p: u64) -> (u64, Vec<u64>) {
let mut subfactors = Vec::new();
let mut q = n / p;
let mut r = n % p;
while r == 0 {
subfactors.push(p);
n = q;
q = n / p;
r = n % p;
}
(n, subfactors)
}
pub fn trial_factorization(n: u64) -> Vec<u64> {
let mut n = n;
let mut factors = Vec::new();
let (num, division_by_two) = subfactors(n, 2);
n = num; // is there a clean way to avoid this assignment?
factors.extend(division_by_two);
let (num, division_by_three) = subfactors(n, 3);
n = num;
factors.extend(division_by_three);
let mut p = 5;
while p * p <= n
{
let (num, division_by_p) = subfactors(n, p);
n = num;
factors.extend(division_by_p);
p += 2;
let (num, division_by_p_plus_two) = subfactors(n, p);
n = num;
factors.extend(division_by_p_plus_two);
p += 4;
}
if n >= 1 { factors.push(n); }
factors
}
fn root(n: u64, f: u64) -> u64 {
let mut n = n;
let mut result = 0;
while n % f == 0 {
result += 1;
n /= f;
}
result
}
pub fn prime_factorization(n: u64) -> Vec<(u64, u64)> {
let factors = trial_factorization(n);
let exponents = factors.iter().map( |&f| root(n, f) );
factors.iter().zip(exponents).map( |(&i, j)| (i, j) ).collect()
}
#[cfg(test)]
mod tests {
use euler::prime::trial_factorization;
#[test]
fn test() {
assert_eq!(trial_factorization(20).len(), 3);
}
}