Skip to content

Commit

Permalink
Solve 36, 37, 45, 53 in rust
Browse files Browse the repository at this point in the history
  • Loading branch information
LivInTheLookingGlass committed Aug 26, 2024
1 parent 4d65f88 commit 6da6964
Show file tree
Hide file tree
Showing 15 changed files with 311 additions and 50 deletions.
8 changes: 4 additions & 4 deletions rust/src/include/factors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub struct ProperDivisors<I>
next_size: usize,
}

pub fn proper_divisors<I>(num: I) -> ProperDivisors<I>
pub fn proper_divisors<I>(num: I) -> impl Iterator<Item = I>
where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I> + 'static
{
return ProperDivisors::<I>::new(num);
Expand Down Expand Up @@ -48,9 +48,9 @@ where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I> +
return None;
}
if self.next_size == 0 {
self.next_size += 1;
return Some(one());
}
self.next_size += 1;
return Some(one());
}
while self.curr_index < self.current_batch.len() {
let result = self.current_batch[self.curr_index];
self.curr_index += 1;
Expand Down
81 changes: 81 additions & 0 deletions rust/src/include/fibonacci.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
use std::ops::{Add,Mul};

use num_traits::{one,zero,One,Zero};

use crate::include::iter_cache::cache_iterator;

pub fn fib<I>() -> impl Iterator<Item = I> where I: Copy + Zero + One + Add + 'static {
return cache_iterator(Fibonacci::<I>::new());
}

pub fn fib_by_3<I>() -> impl Iterator<Item = I> where I: Copy + Zero + One + Add + Mul + 'static {
return cache_iterator(FibonacciBy3::<I>::new());
}

pub struct Fibonacci<I> {
a: I,
b: I,
}

impl<I> Default for Fibonacci<I> where I: Zero + One {
fn default() -> Self {
return Fibonacci::<I>{
a: zero(),
b: one(),
};
}
}

impl<I> Fibonacci<I> where I: Zero + One {
pub fn new() -> Self {
return Default::default();
}
}

impl<I> Iterator for Fibonacci<I> where I: Zero + One + Add + Copy {
type Item = I;

fn next(&mut self) -> Option<Self::Item> {
let prior_a = self.a;
let prior_b = self.b;
self.b = self.a + self.b;
self.a = prior_b;
return Some(prior_a);
}
}

pub struct FibonacciBy3<I> {
a: I,
b: I,
}

impl<I> Default for FibonacciBy3<I> where I: Zero + One {
fn default() -> Self {
let two = one::<I>() + one();
let four = two + two;
return FibonacciBy3::<I>{
a: two,
b: four + four,
};
}
}

impl<I> FibonacciBy3<I> where I: Zero + One + Add {
pub fn new() -> Self {
return Default::default();
}
}

impl<I> Iterator for FibonacciBy3<I> where I: Zero + One + Add + Mul + Copy {
type Item = I;

fn next(&mut self) -> Option<Self::Item> {
let two = one() + one();
let four = two + two;
let prior_a = self.a;
let prior_b = self.b;
self.b = four * self.a + self.b;
self.a = prior_b;
return Some(prior_a);
}
}
8 changes: 8 additions & 0 deletions rust/src/include/iter_cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ use std::sync::Once;
static INIT: Once = Once::new();
static mut CACHE_MAP: Option<RwLock<HashMap<(TypeId, TypeId), Mutex<Vec<Box<dyn std::any::Any>>>>>> = None;

pub fn cache_iterator<I, T>(iterator: I) -> impl Iterator<Item = T>
where
I: Iterator<Item = T> + 'static,
T: Copy + 'static
{
return CachingIterator::new(iterator);
}

pub struct CachingIterator<I, T>
where
I: Iterator<Item = T> + 'static,
Expand Down
1 change: 1 addition & 0 deletions rust/src/include/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
pub mod iter_cache;
pub mod factors;
pub mod fibonacci;
pub mod math;
pub mod primes;
pub mod problems;
Expand Down
37 changes: 12 additions & 25 deletions rust/src/include/primes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@ use std::ops::{Add,Div,Mul,Rem};

use num_traits::{one,zero,One,Zero};

use crate::include::iter_cache::CachingIterator;
use crate::include::iter_cache::cache_iterator;

pub struct Eratosthenes<I>
where I: Hash
{
pub struct Eratosthenes<I> where I: Hash {
sieve: HashMap<I, Vec<I>>,
prime: I,
candidate: I,
}

impl<I> Default for Eratosthenes<I>
where I: Hash + One + Zero + Add
{
impl<I> Default for Eratosthenes<I> where I: Hash + One + Zero + Add {
fn default() -> Self {
return Eratosthenes::<I>{
sieve: HashMap::new(),
Expand All @@ -27,17 +23,13 @@ where I: Hash + One + Zero + Add
}
}

impl<I> Eratosthenes<I>
where I: Hash + One + Zero + Add
{
impl<I> Eratosthenes<I> where I: Hash + One + Zero + Add {
pub fn new() -> Eratosthenes<I> {
return Default::default();
}
}

impl<I> Iterator for Eratosthenes<I>
where I: Hash + One + Zero + Add + Mul + Ord + Copy
{
impl<I> Iterator for Eratosthenes<I> where I: Hash + One + Zero + Add + Mul + Ord + Copy {
type Item = I;

fn next(&mut self) -> Option<Self::Item> {
Expand Down Expand Up @@ -68,25 +60,19 @@ where I: Hash + One + Zero + Add + Mul + Ord + Copy
}
}

pub fn primes<I>() -> impl Iterator<Item = I>
where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static
{
return CachingIterator::new(Eratosthenes::new());
pub fn primes<I>() -> impl Iterator<Item = I> where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static {
return cache_iterator(Eratosthenes::new());
}

pub fn primes_until<I>(x: I) -> impl Iterator<Item = I>
where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static
{
pub fn primes_until<I>(x: I) -> impl Iterator<Item = I> where I: Hash + One + Zero + Add + Mul + Ord + Copy + 'static {
return primes::<I>().take_while(move |n| *n < x);
}

pub struct PrimeFactors<I>
{
pub struct PrimeFactors<I> {
number: I
}

impl<I> PrimeFactors<I>
{
impl<I> PrimeFactors<I> {
pub fn new(x: I) -> PrimeFactors<I> {
return PrimeFactors{
number: x
Expand All @@ -113,7 +99,8 @@ where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I> +
}
}

pub fn prime_factors<I>(x: I) -> PrimeFactors<I>
pub fn prime_factors<I>(x: I) -> impl Iterator<Item = I>
where I: Hash + Zero + One + Add + Ord + Copy + Div<Output=I> + Rem<Output=I> + 'static
{
return PrimeFactors::new(x);
}
Expand Down
8 changes: 8 additions & 0 deletions rust/src/include/problems.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ use crate::p~N::p~N;
});
use crate::p0027::p0027;
use crate::p0034::p0034;
use crate::p0036::p0036;
use crate::p0037::p0037;
use crate::p0045::p0045;
use crate::p0053::p0053;
use crate::p0069::p0069;
use crate::p0076::p0076;
use crate::p0077::p0077;
Expand Down Expand Up @@ -44,6 +48,10 @@ pub fn get_problem<'b>(n: usize) -> Option<ProblemRef<'b>> {
24 => Some(( &24, p0024, false)),
27 => Some(( &27, p0027, true)),
34 => Some(( &34, p0034, false)),
36 => Some(( &36, p0036, false)),
37 => Some(( &37, p0037, false)),
45 => Some(( &45, p0045, false)),
53 => Some(( &53, p0053, false)),
69 => Some(( &69, p0069, false)),
76 => Some(( &76, p0076, false)),
77 => Some(( &77, p0077, false)),
Expand Down
9 changes: 8 additions & 1 deletion rust/src/include/utils.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::string::ToString;

#[cfg(not(any(target_arch="wasm32", target_arch="wasm64")))]
use std::fs::read_to_string;
#[cfg(not(any(target_arch="wasm32", target_arch="wasm64")))]
Expand Down Expand Up @@ -53,4 +55,9 @@ pub fn get_answer(n: usize) -> Answer {
}
}
panic!("Answer not found");
}
}

pub fn is_palindrome<I>(x: I) -> bool where I: ToString {
let s = x.to_string();
return s == s.chars().rev().collect::<String>();
}
4 changes: 4 additions & 0 deletions rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ pub mod p~N;
});
pub mod p0027;
pub mod p0034;
pub mod p0036;
pub mod p0037;
pub mod p0045;
pub mod p0053;
pub mod p0069;
pub mod p0076;
pub mod p0077;
Expand Down
30 changes: 26 additions & 4 deletions rust/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ pub mod p~N;
});
pub mod p0027;
pub mod p0034;
pub mod p0036;
pub mod p0037;
pub mod p0045;
pub mod p0053;
pub mod p0069;
pub mod p0076;
pub mod p0077;
Expand All @@ -40,9 +44,9 @@ fn main() {
for i in sieve {
println!("{}", i);
}
for i in 4..100 {
println!("{}: {:?}", i, factors::proper_divisors(i).collect::<Vec<u16>>());
}
for i in 4..100 {
println!("{}: {:?}", i, factors::proper_divisors(i).collect::<Vec<u16>>());
}
let supported = generate_supported_problems(false);

for id in supported {
Expand Down Expand Up @@ -73,6 +77,10 @@ seq!(N in 01..=20 {
#[case::problem_24(24)]
#[case::problem_27(27)]
#[case::problem_34(34)]
#[case::problem_36(36)]
#[case::problem_37(37)]
#[case::problem_45(45)]
#[case::problem_53(53)]
#[case::problem_69(69)]
#[case::problem_76(76)]
#[case::problem_77(77)]
Expand Down Expand Up @@ -100,7 +108,6 @@ fn test_problem(#[case] id: usize) -> Result<(), String> {
}
});


#[cfg(test)]
#[test]
fn test_primes() -> Result<(), String> {
Expand Down Expand Up @@ -128,3 +135,18 @@ fn test_prime_factors() -> Result<(), String> {
}
Ok(())
}

#[cfg(test)]
#[test]
fn test_proper_divisors() -> Result<(), String> {
for i in 4..1024 {
let divisors = factors::proper_divisors(i).collect::<Vec<u16>>();
for &factor in divisors.iter() {
if factor == 1 {
continue;
}
assert!(divisors.iter().any(|&x| x * factor == i));
}
}
Ok(())
}
12 changes: 2 additions & 10 deletions rust/src/p0002.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,9 @@ terms. By starting with 1 and 2, the first 10 terms will be:
By considering the terms in the Fibonacci sequence whose values do not exceed
four million, find the sum of the even-valued terms.
*/
use crate::include::fibonacci::fib_by_3;
use crate::include::utils::Answer;

pub fn p0002() -> Answer {
let mut answer: u64 = 0;
let mut i = 2;
let mut j = 8;
while i < 4000000 {
answer += i;
let tmp = 4 * j + i;
i = j;
j = tmp;
}
return Answer::Int(answer.into());
return Answer::Int(fib_by_3::<u64>().take_while(|x| *x < 4000000).sum::<u64>().into());
}
7 changes: 1 addition & 6 deletions rust/src/p0004.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,7 @@ Find the largest palindrome made from the product of two 3-digit numbers.
*/
use itertools::Itertools;

use crate::include::utils::Answer;

fn is_palindrome(x: u32) -> bool {
let s = x.to_string();
return s == s.chars().rev().collect::<String>();
}
use crate::include::utils::{is_palindrome,Answer};

pub fn p0004() -> Answer {
let mut answer: u32 = 0;
Expand Down
26 changes: 26 additions & 0 deletions rust/src/p0036.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
Project Euler Problem 36
Rust implementing a `reverse_bits()` function made this much more pleasant than expected
Problem:
The decimal number, 585 = 10010010012 (binary), is palindromic in both bases.
Find the sum of all numbers, less than one million, which are palindromic in
base 10 and base 2.
(Please note that the palindromic number, in either base, may not include
leading zeros.)
*/
use crate::include::utils::{is_palindrome,Answer};

pub fn p0036() -> Answer {
let mut answer: u64 = 0;
for x in 1..1000000 {
if (x == x.reverse_bits::<u64>()) && is_palindrome(x) {
answer += x;
}
}
return Answer::Int(answer.into());
}
Loading

0 comments on commit 6da6964

Please sign in to comment.