From 03513b9f020319799fcc1104b2cc9d8ec6bdbf04 Mon Sep 17 00:00:00 2001 From: Olivia Appleton Date: Mon, 8 Jul 2024 23:15:14 -0500 Subject: [PATCH] Add partial rust prime infrastructure --- .gitignore | 3 ++- rust/src/main.rs | 19 +++++++++++++ rust/src/primes.rs | 66 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 rust/src/primes.rs diff --git a/.gitignore b/.gitignore index fe0b1aa9..b1bcc5f4 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ venv/** csharp/*/obj csharp/*/bin **/TestResults -docs/_build \ No newline at end of file +docs/_build +rust/target \ No newline at end of file diff --git a/rust/src/main.rs b/rust/src/main.rs index 35d55897..8953b578 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -1,5 +1,7 @@ #[cfg(test)] use std::time::Duration; +// #[cfg(test)] +// use std::iter::zip; use seq_macro::seq; #[cfg(test)] @@ -8,6 +10,7 @@ use rstest::rstest; seq!(N in 0001..=0002 { mod p~N; }); +mod primes; type ProblemType = fn() -> u64; type ProblemRef<'a> = (&'a str, ProblemType, u64); @@ -17,6 +20,10 @@ const ANSWERS: [ProblemRef; 2] = [ ]; fn main() { + // let sieve = primes::ModifiedEratosthenes::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); @@ -37,3 +44,15 @@ fn test_problem(#[case] idx: usize) -> Result<(), String> { Ok(()) } }); + + +// #[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(()) +// } diff --git a/rust/src/primes.rs b/rust/src/primes.rs new file mode 100644 index 00000000..e406495a --- /dev/null +++ b/rust/src/primes.rs @@ -0,0 +1,66 @@ +use std::collections::HashMap; + +pub struct ModifiedEratosthenes { + sieve: HashMap, + prime: u64, + candidate: u64, + recurse: Option> +} + +impl ModifiedEratosthenes { + pub fn new() -> ModifiedEratosthenes { + return ModifiedEratosthenes{ + sieve: HashMap::new(), + prime: 0, + candidate: 2, + recurse: None + }; + } +} + +impl Iterator for ModifiedEratosthenes { + type Item = u64; + + fn next(&mut self) -> Option { + 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"); + } + 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(); + } + 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.sieve.insert(candidate, step); + } + } +} \ No newline at end of file