Skip to content

Commit 481a307

Browse files
authored
Prime sieve divs (#78)
* first draft * finish * revert * consistent var name * better way * nits * golf --------- Co-authored-by: Luke Videckis <lukevideckis@gmail.com>
1 parent 2436ac4 commit 481a307

File tree

4 files changed

+60
-8
lines changed

4 files changed

+60
-8
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ path = "examples/numbers/primes_factorize.rs"
8080
name = "primes_is_prime"
8181
path = "examples/numbers/primes_is_prime.rs"
8282

83+
[[example]]
84+
name = "primes_divisorize"
85+
path = "examples/numbers/primes_divisorize.rs"
86+
8387
[[example]]
8488
name = "manacher"
8589
path = "examples/strings/manacher.rs"
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// verification-helper: PROBLEM https://onlinejudge.u-aizu.ac.jp/courses/lesson/2/ITP1/all/ITP1_1_A
2+
3+
use programming_team_code_rust::numbers::primes::Primes;
4+
5+
fn main() {
6+
let n = 100_000;
7+
let mut divs = vec![vec![]; n + 1];
8+
for i in 1..=n {
9+
for j in 1..=n / i {
10+
divs[i * j].push(i);
11+
}
12+
}
13+
14+
let primes = Primes::new(n + 1);
15+
16+
#[allow(clippy::needless_range_loop)]
17+
for i in 1..=n {
18+
let mut all_divisors = primes.divisorize(i);
19+
all_divisors.sort();
20+
assert_eq!(all_divisors, divs[i]);
21+
}
22+
23+
println!("Hello World");
24+
}

examples/numbers/primes_factorize.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,12 @@ fn main() {
1919
let mut exps = vec![0; 1001];
2020
let mut prev_factor = 0;
2121

22-
primes.factorize(x, |factor| {
22+
for factor in primes.factorize(x) {
2323
assert!(prev_factor <= factor);
2424
exps[factor] += 1;
2525
lcm_exps[factor] = lcm_exps[factor].max(exps[factor]);
2626
prev_factor = factor;
27-
});
27+
}
2828
}
2929

3030
let mut lcm = 1;

src/numbers/primes.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
/// let primes = Primes::new(100);
88
/// assert_eq!(primes.is_prime(2), true);
99
/// assert_eq!(primes.is_prime(4), false);
10-
/// let mut factors = vec![];
11-
/// primes.factorize(12, |factor| factors.push(factor));
12-
/// assert_eq!(factors, vec![2, 2, 3]);
10+
/// assert_eq!(primes.factorize(12), [2, 2, 3]);
11+
/// assert_eq!(primes.divisorize(12), [1, 2, 4, 3, 6, 12]);
12+
/// assert!(std::panic::catch_unwind(|| primes.divisorize(0)).is_err());
1313
/// ```
1414
pub struct Primes {
1515
min_fact: Vec<usize>,
@@ -46,16 +46,40 @@ impl Primes {
4646
x >= 2 && self.min_fact[x] == x
4747
}
4848

49-
/// Calls closure on each prime factor in ascending order
49+
/// Returns a vector of prime factors of the given number
50+
/// The factors are sorted in ascending order
5051
///
5152
/// # Complexity
5253
/// - Time: O(log x)
5354
/// - Space: O(log x)
54-
pub fn factorize(&self, mut x: usize, mut f: impl FnMut(usize)) {
55+
pub fn factorize(&self, mut x: usize) -> Vec<usize> {
56+
let mut facts = vec![];
5557
while x > 1 {
5658
let p = self.min_fact[x];
57-
f(p);
59+
facts.push(p);
5860
x /= p;
5961
}
62+
facts
63+
}
64+
65+
/// Returns a vector of all divisors of the given number
66+
///
67+
/// # Complexity
68+
/// - Time: O(number_of_divisors(x))
69+
/// - Space: O(number_of_divisors(x))
70+
pub fn divisorize(&self, mut x: usize) -> Vec<usize> {
71+
assert_ne!(x, 0);
72+
let mut divs = vec![1];
73+
while x > 1 {
74+
let (p, len1) = (self.min_fact[x], divs.len());
75+
while self.min_fact[x] == p {
76+
let len2 = divs.len();
77+
for i in len2 - len1..len2 {
78+
divs.push(divs[i] * p);
79+
}
80+
x /= p;
81+
}
82+
}
83+
divs
6084
}
6185
}

0 commit comments

Comments
 (0)