73 lines
1.5 KiB
Rust
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);
|
|
}
|
|
}
|