diff --git a/src/euler47/Cargo.toml b/src/euler47/Cargo.toml new file mode 100644 index 0000000..069acda --- /dev/null +++ b/src/euler47/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "euler47" +version = "0.1.0" +edition = "2024" + +[dependencies] +itertools = "0.14.0" +primes = { version = "*", path = "../../lib/primes" } + +[dev-dependencies] +rstest = "0.25.0" diff --git a/src/euler47/src/main.rs b/src/euler47/src/main.rs new file mode 100644 index 0000000..993d1a1 --- /dev/null +++ b/src/euler47/src/main.rs @@ -0,0 +1,76 @@ +use itertools::Itertools; +use primes::Primes; + +const MAX: usize = 1_000_000; + +fn main() { + let primes = Primes::get_between(2, MAX); + + 'outer: for number in 2..MAX { + for i in 0..=3 { + let factors = factorize_unique(number + i, &primes); + if factors.len() != 4 { + continue 'outer; + } + } + println!("{number}"); + break; + } +} + +fn factorize(n: usize, primes: &Primes) -> Vec { + if primes.contains(&n) { + return vec![n]; + } + + let mut remaining = n; + let mut result = vec![]; + 'outer: loop { + if remaining == 1 { + break 'outer; + } + 'inner: for prime in primes.iter().take_while(|p| **p <= remaining) { + let remainder = remaining % prime; + if remainder == 0 { + result.push(prime.to_owned()); + remaining /= prime; + break 'inner; + } + } + } + result +} + +fn factorize_unique(n: usize, primes: &Primes) -> Vec { + factorize(n, primes).into_iter().unique().collect() +} + +#[cfg(test)] +mod tests { + use primes::Primes; + + use crate::{factorize, factorize_unique}; + + use rstest::rstest; + + #[rstest] + #[case(14, vec![2, 7])] + #[case(15, vec![3, 5])] + #[case(644, vec![2, 2, 7, 23])] + #[case(645, vec![3, 5, 43])] + #[case(646, vec![2, 17, 19])] + fn factorization(#[case] input: usize, #[case] expected: Vec) { + let primes = Primes::get_between(2, input); + let result = factorize(input, &primes); + assert_eq!(result, expected); + } + + #[rstest] + #[case(644, vec![2, 7, 23])] + #[case(645, vec![3, 5, 43])] + fn factorization_unique(#[case] input: usize, #[case] expected: Vec) { + let primes = Primes::get_between(2, input); + let result = factorize_unique(input, &primes); + assert_eq!(result, expected); + } +}