Skip to content

Commit d100bed

Browse files
committed
12
1 parent a598d2a commit d100bed

File tree

2 files changed

+118
-0
lines changed

2 files changed

+118
-0
lines changed

src/bin/12.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use project_euler::*;
2+
3+
fn main() {
4+
let mut current_factorization = prime_factorization(1);
5+
let mut next = 2;
6+
let mut next_factorization = prime_factorization(next);
7+
loop {
8+
current_factorization.merge(&next_factorization);
9+
current_factorization.remove_prime_factor(2, 1);
10+
if current_factorization.num_factors() > 500 {
11+
println!("{}", current_factorization.value());
12+
break;
13+
}
14+
15+
current_factorization = next_factorization;
16+
next += 1;
17+
next_factorization = prime_factorization(next);
18+
}
19+
}

src/lib.rs

+99
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,102 @@ pub fn is_palindromic_chars(chars: Vec<u8>) -> bool {
3333
}
3434
true
3535
}
36+
37+
use std::collections::HashMap;
38+
39+
#[derive(Debug, Default, Clone, PartialEq, Eq)]
40+
pub struct PrimeFactorization {
41+
pub map: HashMap<u64, u32>,
42+
}
43+
44+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45+
pub struct PrimeFactor {
46+
pub prime: u64,
47+
pub power: u32,
48+
}
49+
50+
impl PrimeFactorization {
51+
pub fn add_prime_factor(&mut self, prime: u64, power: u32) {
52+
use std::collections::hash_map::Entry;
53+
match self.map.entry(prime) {
54+
Entry::Occupied(mut entry) => *entry.get_mut() += power,
55+
Entry::Vacant(entry) => {
56+
entry.insert(power);
57+
},
58+
}
59+
}
60+
61+
pub fn remove_prime_factor(&mut self, prime: u64, power: u32) {
62+
let current = self.map.get_mut(&prime).unwrap();
63+
*current = current.checked_sub(power).unwrap();
64+
}
65+
66+
pub fn merge(&mut self, other: &PrimeFactorization) {
67+
for (prime, power) in &other.map {
68+
self.add_prime_factor(*prime, *power);
69+
}
70+
}
71+
72+
pub fn num_factors(&self) -> u32 {
73+
self.map.iter().map(|(_, power)| power + 1).product()
74+
}
75+
76+
pub fn value(&self) -> u64 {
77+
self.map.iter().map(|(prime, power)| prime.pow(*power)).product()
78+
}
79+
80+
pub fn into_vec(self) -> Vec<PrimeFactor> {
81+
self.map.into_iter().map(|(prime, power)| PrimeFactor { prime, power }).collect()
82+
}
83+
}
84+
85+
pub fn prime_factorization(mut n: u64) -> PrimeFactorization {
86+
let mut result = Default::default();
87+
88+
if n == 1 {
89+
result
90+
} else if n == 2 || n == 3 {
91+
result.add_prime_factor(n, 1);
92+
result
93+
} else {
94+
while n > 3 {
95+
let mut reduced = false;
96+
let upper_factor = (n as f64).sqrt().floor() as u64;
97+
for i in 2..=upper_factor {
98+
if n % i == 0 {
99+
result.add_prime_factor(i, 1);
100+
n /= i;
101+
reduced = true;
102+
break;
103+
}
104+
}
105+
if !reduced {
106+
// This is a prime.
107+
result.add_prime_factor(n, 1);
108+
n = 1;
109+
}
110+
}
111+
112+
if n == 3 {
113+
result.add_prime_factor(3, 1);
114+
} else if n == 2 {
115+
result.add_prime_factor(2, 1);
116+
}
117+
118+
result
119+
}
120+
}
121+
122+
#[cfg(test)]
123+
mod tests {
124+
use super::*;
125+
126+
#[test]
127+
fn test_primie_factorization() {
128+
assert_eq!(prime_factorization(1).into_vec(), vec![]);
129+
assert_eq!(prime_factorization(2).into_vec(), vec![PrimeFactor { prime: 2, power: 1 }]);
130+
assert_eq!(prime_factorization(3).into_vec(), vec![PrimeFactor { prime: 3, power: 1 }]);
131+
assert_eq!(prime_factorization(4).into_vec(), vec![PrimeFactor { prime: 2, power: 2 }]);
132+
assert_eq!(prime_factorization(500).into_vec(), vec![PrimeFactor { prime: 5, power: 3 }, PrimeFactor { prime: 2, power: 2 }]);
133+
}
134+
}

0 commit comments

Comments
 (0)