Skip to content

Commit

Permalink
PotentialPrimes optimisation (#163)
Browse files Browse the repository at this point in the history
* `PotentialPrimes`: generate starting from 7
  * Removed `PrimeDivisors`, which required `PotentialPrimes` and was used in only one solution.
  * This change reduced the running time of solution 27 from 7 ms to 4 ms because of the related change in `is_prime_td`.
* Formatted
  • Loading branch information
tfpf authored Sep 21, 2024
1 parent ccfd0ee commit abe0338
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 57 deletions.
28 changes: 27 additions & 1 deletion src/solutions/largest_prime_factor.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,34 @@
use crate::utils;

/// Determine the largest prime factor of the given number.
///
/// * `num`
fn largest_prime_factor(mut num: i64) -> i64 {
// Not divisible by 2, 3 or 5. Look for other factors.
utils::PotentialPrimes::new(num)
.map_while(|potential_prime| {
if potential_prime > num {
None
} else if num % potential_prime != 0 {
// Dummy result so that the loop continues looking for factors and
// does not terminate.
Some(0)
} else {
// Found a potential prime factor. Eliminate it. Doing this ensures
// that all factors found are actually prime factors.
while num % potential_prime == 0 {
num /= potential_prime;
}
Some(potential_prime)
}
})
.max()
.unwrap()
}

pub fn solve() -> i64 {
let num: i64 = 600851475143;
let largest_pf = utils::PrimeDivisors::new(num).max().unwrap().0;
let largest_pf = largest_prime_factor(num);

assert_eq!(largest_pf, 6857);
largest_pf
Expand Down
8 changes: 3 additions & 5 deletions src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,9 @@ pub fn is_prime(num: i64) -> bool {
/// * `num` Must not be divisible by 2, 3 or 5. Must exceed 5.
fn is_prime_td(num: i64) -> bool {
// No need to search for composite factors. We'll find prime factors (if
// any) faster.
PotentialPrimes::new(isqrt(num))
.skip(3)
.all(|potential_prime| num % potential_prime != 0)
// any) faster. Don't bother generating prime numbers. Potential prime
// numbers are faster to generate.
PotentialPrimes::new(isqrt(num)).all(|potential_prime| num % potential_prime != 0)
}

/// Check whether the given number is prime using the Miller-Rabin test.
Expand Down Expand Up @@ -236,7 +235,6 @@ pub use iterators::divisors::Divisors;
pub use iterators::fibonacci::Fibonacci;
pub use iterators::polygonal::Polygonal;
pub use iterators::potential_primes::PotentialPrimes;
pub use iterators::prime_divisors::PrimeDivisors;
pub use iterators::pythagorean_triplets::PythagoreanTriplets;

#[cfg(test)]
Expand Down
1 change: 0 additions & 1 deletion src/utils/iterators.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,4 @@ pub mod divisors;
pub mod fibonacci;
pub mod polygonal;
pub mod potential_primes;
pub mod prime_divisors;
pub mod pythagorean_triplets;
13 changes: 4 additions & 9 deletions src/utils/iterators/potential_primes.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/// Potential prime numbers. Generates some small prime numbers and numbers
/// coprime to 30. Used for wheel factorisation with 2, 3 and 5.
/// Potential prime numbers. Generates numbers coprime to 30, starting from 7.
/// Used for wheel factorisation with 2, 3 and 5.
pub struct PotentialPrimes {
limit: i64,
num: i64,
Expand All @@ -11,20 +11,15 @@ impl PotentialPrimes {
PotentialPrimes {
limit,
num: 1,
offset: [4, 2, 4, 2, 4, 6, 2, 6].into_iter().cycle(),
offset: [6, 4, 2, 4, 2, 4, 6, 2].into_iter().cycle(),
}
}
}

impl Iterator for PotentialPrimes {
type Item = i64;
fn next(&mut self) -> Option<i64> {
self.num += match self.num {
1 => 1,
2 => 1,
3 | 5 => 2,
_ => self.offset.next().unwrap(),
};
self.num += self.offset.next().unwrap();
if self.num > self.limit {
None
} else {
Expand Down
41 changes: 0 additions & 41 deletions src/utils/iterators/prime_divisors.rs

This file was deleted.

0 comments on commit abe0338

Please sign in to comment.