From 37f40689dc2f7705165cea805f546dc5b8734a01 Mon Sep 17 00:00:00 2001 From: timeshifter Date: Wed, 12 Mar 2025 16:17:41 +0100 Subject: [PATCH] add 21 --- src/euler21/Cargo.toml | 11 +++++ src/euler21/src/main.rs | 105 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 src/euler21/Cargo.toml create mode 100644 src/euler21/src/main.rs diff --git a/src/euler21/Cargo.toml b/src/euler21/Cargo.toml new file mode 100644 index 0000000..4e248b6 --- /dev/null +++ b/src/euler21/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "euler21" +version = "0.1.0" +edition = "2024" + +[profile.release] +debug = true +lto = "off" + +[dependencies] +proper_divisors = { version = "*", path = "../../lib/proper_divisors" } diff --git a/src/euler21/src/main.rs b/src/euler21/src/main.rs new file mode 100644 index 0000000..e18b1e1 --- /dev/null +++ b/src/euler21/src/main.rs @@ -0,0 +1,105 @@ +use proper_divisors::ProperDivisors; +use std::collections::HashMap; + +const MIN: usize = 2; +const MAX: usize = 10_000; + +fn main() { + let pd = ProperDivisors::get_between(MIN, MAX); + let mut map = NumberDivisorSumMap::build(pd); + + let mut sum = 0; + + for i in MIN..MAX { + if let Some(pair) = map.find_amicable_number(i) { + sum += pair + i; + } + } + + println!("{sum}"); +} + +#[derive(Debug)] +struct NumberDivisorSumMap { + map: HashMap, +} + +impl NumberDivisorSumMap { + fn build(pd: ProperDivisors) -> Self { + let mut number_divisor_sum_map = HashMap::new(); + + for number in pd.min..pd.max { + let sum: usize = pd.get(number).iter().sum(); + number_divisor_sum_map.insert(number, sum); + } + Self { + map: number_divisor_sum_map, + } + } + + fn get(&self, key: &usize) -> Option<&usize> { + self.map.get(key) + } + + fn remove(&mut self, key: &usize) { + self.map.remove(key); + } + + fn remove_all(&mut self, keys: &[usize]) { + for key in keys { + self.remove(key); + } + } + + fn find_amicable_number(&mut self, number: usize) -> Option { + let possible_pair = match self.get(&number) { + None => return None, + Some(possible_pair) => possible_pair.to_owned(), + }; + + if possible_pair == number { + return None; + } + + if self.get(&possible_pair) == Some(&number) { + self.remove_all(&[number, possible_pair]); + return Some(possible_pair); + } + + None + } +} + +#[cfg(test)] +mod tests { + use proper_divisors::ProperDivisors; + + use crate::NumberDivisorSumMap; + + #[test] + fn case_pair() { + let pd = ProperDivisors::get_between(2, 10_000); + let mut number_divisor_sum_map = NumberDivisorSumMap::build(pd); + let result = number_divisor_sum_map.find_amicable_number(220); + + assert_eq!(result, Some(284)); + } + + #[test] + fn case_not_pair() { + let pd = ProperDivisors::get_between(2, 10_000); + let mut number_divisor_sum_map = NumberDivisorSumMap::build(pd); + let result = number_divisor_sum_map.find_amicable_number(221); + + assert_eq!(result, None); + } + + #[test] + fn case_false_pair() { + let pd = ProperDivisors::get_between(2, 10); + let mut number_divisor_sum_map = NumberDivisorSumMap::build(pd); + let result = number_divisor_sum_map.find_amicable_number(6); + + assert_eq!(result, None); + } +}