1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
/// 非負整数を素因数分解です。
pub trait PrimeFactorization: Sized {
/// (素因数, べき) のベクタを返します。
///
/// # Examples
/// ```
/// use prime_factorization::PrimeFactorization;
///
/// assert_eq!(2_u32.prime_factorization(), vec![(2, 1)]);
/// // 90 = 2 * 3 * 3 * 5
/// assert_eq!(90_u32.prime_factorization(), vec![(2, 1), (3, 2), (5, 1)]);
/// ```
fn prime_factorization(self) -> Vec<(Self, Self)>;
}
macro_rules! impl_prime_factorization {
($($t:ty),+) => {
$(
impl PrimeFactorization for $t {
fn prime_factorization(self) -> Vec<(Self, Self)> {
let mut res = Vec::new();
let mut n = self;
for k in ((2 as Self)..).take_while(|&k| k.saturating_mul(k) <= self) {
if n % k == 0 {
let mut e = 0;
while n % k == 0 {
e += 1;
n /= k;
}
res.push((k, e));
}
}
if n > 1 {
res.push((n, 1));
}
res
}
}
)+
};
}
impl_prime_factorization!(usize, u32, u64);
#[cfg(test)]
mod tests {
use crate::PrimeFactorization;
#[test]
fn small_test() {
assert_eq!(0_u32.prime_factorization(), vec![]);
assert_eq!(1_u32.prime_factorization(), vec![]);
assert_eq!(2_u32.prime_factorization(), vec![(2, 1)]);
assert_eq!(3_u32.prime_factorization(), vec![(3, 1)]);
assert_eq!(4_u32.prime_factorization(), vec![(2, 2)]);
}
#[test]
fn test() {
for n in 1..1000 {
let f = (n as u32).prime_factorization();
let mut res = 1;
for (p, e) in f {
res *= p.pow(e);
}
assert_eq!(res, n);
}
}
}