From 3d4e350b899293f08836ddaf034082e0a64350a0 Mon Sep 17 00:00:00 2001 From: Philippe Zwietering Date: Tue, 27 Jun 2023 17:11:35 +0200 Subject: [PATCH] WIP PE 095, getting bullied by the borrow checker --- projecteuler/095/Cargo.toml | 8 ++++ projecteuler/095/src/main.rs | 84 ++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+) create mode 100644 projecteuler/095/Cargo.toml create mode 100644 projecteuler/095/src/main.rs diff --git a/projecteuler/095/Cargo.toml b/projecteuler/095/Cargo.toml new file mode 100644 index 0000000..fca4e93 --- /dev/null +++ b/projecteuler/095/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "main" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/projecteuler/095/src/main.rs b/projecteuler/095/src/main.rs new file mode 100644 index 0000000..bc6baae --- /dev/null +++ b/projecteuler/095/src/main.rs @@ -0,0 +1,84 @@ +use std::{ + collections::{HashMap, HashSet}, + time::Instant, + u64::MAX, +}; + +fn sum_of_divisors(n: u64, divisor_map: &HashMap>) -> (u64, HashSet) { + let max_div = n / 2 + 1; + let mut result = HashSet::new(); + + for i in 1..=max_div { + if n % i == 0 { + result.insert(i); + if let Some(div_set) = divisor_map.get(&(n / i)) { + result = result.union(div_set).collect(); + } + } + } + + return (result.iter().sum(), result); +} + +fn find_longest_amicable_chain(limit: u64) -> u64 { + let mut chain_numbers = HashSet::new(); + let mut max_chain_length = 0; + let mut smallest_chain_number = MAX; + let mut divisor_sums = HashMap::new(); + + for n in 0..limit { + if chain_numbers.contains(&n) { + continue; + } + + let l = n; + let mut chain = vec![l]; + loop { + let (l, l_divisors) = sum_of_divisors(l, &divisor_sums); + divisor_sums.insert(l, l_divisors); + + if l >= limit { + chain.clear(); + break; + } + + if chain.contains(&l) { + break; + } + + if chain_numbers.contains(&l) { + chain.clear(); + break; + } + + chain.push(l); + // We want to push numbers into the found_numbers even if the chain might get too big + // in the future, since this is just a list of numbers that we don't want to + // investigate further. + chain_numbers.insert(l); + } + + if chain.len() > max_chain_length { + max_chain_length = chain.len(); + smallest_chain_number = chain.into_iter().min().unwrap(); + + println!("{}", smallest_chain_number); + } + } + + return smallest_chain_number; +} + +fn main() { + println!("Hello, this is Patrick!"); + let now = Instant::now(); + + const LIMIT: u64 = 1000000; + + println!( + "Smallest element of amicable chain containing only elements below 1 million: {}", + find_longest_amicable_chain(LIMIT) + ); + + println!("Time passed: {:?}", Instant::now() - now); +}