Skip to content

Commit

Permalink
add final prime infrastructure
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Jul 12, 2024
1 parent 8615339 commit 86a4ca3
Show file tree
Hide file tree
Showing 4 changed files with 110 additions and 61 deletions.
16 changes: 16 additions & 0 deletions rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,6 @@ version = "0.1.0"
edition = "2021"

[dependencies]
itertools = "0.13.0"
rstest = "0.21.0"
seq-macro = "0.3.5"
50 changes: 33 additions & 17 deletions rust/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
#[cfg(test)]
use std::time::Duration;
// #[cfg(test)]
// use std::iter::zip;
#[cfg(test)]
use std::iter::zip;

use seq_macro::seq;
#[cfg(test)]
use rstest::rstest;
#[cfg(test)]
use itertools::Itertools;

seq!(N in 0001..=0002 {
mod p~N;
Expand All @@ -16,14 +18,15 @@ type ProblemType = fn() -> u64;
type ProblemRef<'a> = (&'a str, ProblemType, u64);
const ANSWERS: [ProblemRef; 2] = [
("p0001", p0001::p0001, 233168),
("p0002", p0002::p0002, 4613732)
("p0002", p0002::p0002, 4613732),
// ("p0003", p0003::p0003, 6857),
];

fn main() {
// let sieve = primes::ModifiedEratosthenes::new().take(10);
// for i in sieve {
// println!("{}", i);
// }
let sieve = primes::Eratosthenes::new().take(10);
for i in sieve {
println!("{}", i);
}
for (name, func, answer) in ANSWERS {
let result = func();
println!("Problem {} should return {}. Returned {}!", name, answer, result);
Expand All @@ -46,13 +49,26 @@ fn test_problem(#[case] idx: usize) -> Result<(), String> {
});


// #[cfg(test)]
// #[test]
// fn test_primes() -> Result<(), String> {
// let primes = [2, 3, 5, 7, 11, 13, 17, 19];
// let sieve = primes::ModifiedEratosthenes::new().take(primes.len());
// for (p, s) in zip(primes, sieve) {
// assert_eq!(p, s);
// }
// Ok(())
// }
#[cfg(test)]
#[test]
fn test_primes() -> Result<(), String> {
let primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113];
let sieve = primes::Eratosthenes::new().take(primes.len());
for (p, s) in zip(primes, sieve) {
assert_eq!(p, s);
}
Ok(())
}

#[cfg(test)]
#[test]
fn test_prime_factors() -> Result<(), String> {
for v in primes::Eratosthenes::new().take(15).combinations(2) {
let p = v[0];
let s = v[1];
for f in primes::PrimeFactors::new(p * s) {
assert!(f == p || f == s);
}
}
Ok(())
}
104 changes: 60 additions & 44 deletions rust/src/primes.rs
Original file line number Diff line number Diff line change
@@ -1,66 +1,82 @@
use std::collections::HashMap;

pub struct ModifiedEratosthenes {
sieve: HashMap<u64, u64>,
pub struct Eratosthenes {
sieve: HashMap<u64, Vec<u64>>,
prime: u64,
candidate: u64,
recurse: Option<Box<ModifiedEratosthenes>>
}

impl ModifiedEratosthenes {
pub fn new() -> ModifiedEratosthenes {
return ModifiedEratosthenes{
impl Default for Eratosthenes {
fn default() -> Self {
return Eratosthenes{
sieve: HashMap::new(),
prime: 0,
candidate: 2,
recurse: None
};
}
}

impl Iterator for ModifiedEratosthenes {
impl Eratosthenes {
pub fn new() -> Eratosthenes {
return Default::default();
}
}

impl Iterator for Eratosthenes {
type Item = u64;

fn next(&mut self) -> Option<Self::Item> {
if self.candidate == 2 {
self.candidate = 3;
self.prime = 3;
println!("Returning 2");
return Some(2);
}
let mut candidate = self.candidate;
self.candidate += 2;
loop {
let prime_squared = self.prime * self.prime;
println!("Candidate: {}", candidate);
let step: u64;
if self.sieve.contains_key(&candidate) {
step = self.sieve.remove(&candidate)?;
println!("Candidate in cache as {}", step);
}
else if candidate < prime_squared {
println!("Candidate not in cache, but less than {}", prime_squared);
return Some(candidate);
}
else {
if candidate != prime_squared {
panic!("Something has gone wrong in the sieve");
fn next_prime(sieve: &mut HashMap<u64, Vec<u64>>, candidate: u64) -> u64 {
match sieve.get(&candidate) {
Some(numbers) => {
for num in numbers.to_owned() {
sieve
.entry(candidate + num)
.and_modify(|v| v.push(num))
.or_insert_with(|| vec![num]);
}
sieve.remove(&candidate);
return next_prime(sieve, candidate + 1);
}
step = self.prime * 2;
if self.recurse.is_none() {
self.recurse = Some(Box::new(ModifiedEratosthenes::new()));
let mut recursed = self.recurse.take()?;
let _ = (*recursed).next();
None => {
sieve.insert(candidate * candidate, vec![candidate]);
return candidate;
}
let mut recursed = self.recurse.take()?;
self.prime = ((*recursed).next())?;
}
println!("This is the good part");
candidate += step;
while self.sieve.contains_key(&candidate) {
candidate += step;
}

self.prime = next_prime(&mut self.sieve, self.candidate);
self.candidate = self.prime + 1; // This number will be the next to be tested

return Some(self.prime)
}
}

pub struct PrimeFactors {
number: u64
}

impl PrimeFactors {
pub fn new(x: u64) -> PrimeFactors {
return PrimeFactors{
number: x
};
}
}

impl Iterator for PrimeFactors {
type Item = u64;

fn next(&mut self) -> Option<Self::Item> {
for p in Eratosthenes::new() {
if self.number % p == 0 {
self.number = self.number / p;
return Some(p);
}
else if self.number < p {
break;
}
self.sieve.insert(candidate, step);
}
return None;
}
}
}

0 comments on commit 86a4ca3

Please sign in to comment.