diff --git a/README.md b/README.md index 2bd8670..44e10d8 100644 --- a/README.md +++ b/README.md @@ -120,6 +120,7 @@ such as (but not limited to) Bard and ChatGPT. |[74](https://projecteuler.net/problem=74)|[`digit_factorial_chains.rs`](src/solutions/digit_factorial_chains.rs)| |[75](https://projecteuler.net/problem=75)|[`singular_integer_right_triangles.rs`](src/solutions/singular_integer_right_triangles.rs)| |[76](https://projecteuler.net/problem=76)|[`counting_summations.rs`](src/solutions/counting_summations.rs)| +|[77](https://projecteuler.net/problem=77)|[`prime_summations.rs`](src/solutions/prime_summations.rs)| |[81](https://projecteuler.net/problem=81)|[`path_sum_two_ways.rs`](src/solutions/path_sum_two_ways.rs)| |[85](https://projecteuler.net/problem=85)|[`counting_rectangles.rs`](src/solutions/counting_rectangles.rs)| |[87](https://projecteuler.net/problem=87)|[`prime_power_triples.rs`](src/solutions/prime_power_triples.rs)| diff --git a/src/main.rs b/src/main.rs index 7c73a1d..75ebab2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -89,6 +89,7 @@ fn solve_and_time_one(problem_number: i32) -> bool { 74 => solutions::digit_factorial_chains::solve, 75 => solutions::singular_integer_right_triangles::solve, 76 => solutions::counting_summations::solve, + 77 => solutions::prime_summations::solve, 81 => solutions::path_sum_two_ways::solve, 85 => solutions::counting_rectangles::solve, 87 => solutions::prime_power_triples::solve, diff --git a/src/solutions.rs b/src/solutions.rs index 7792924..0503862 100644 --- a/src/solutions.rs +++ b/src/solutions.rs @@ -58,6 +58,7 @@ pub mod powerful_digit_sum; pub mod prime_digit_replacements; pub mod prime_permutations; pub mod prime_power_triples; +pub mod prime_summations; pub mod quadratic_primes; pub mod reciprocal_cycles; pub mod self_powers; diff --git a/src/solutions/prime_summations.rs b/src/solutions/prime_summations.rs new file mode 100644 index 0000000..f3af2be --- /dev/null +++ b/src/solutions/prime_summations.rs @@ -0,0 +1,38 @@ +use crate::utils; + +pub fn solve() -> i64 { + // Approach is similar to that used for P31. The difference is that the + // maximum denomination is guessed, and that there is no target sum. + const LIMIT: usize = 100; + let primes = utils::SieveOfAtkin::new(LIMIT).iter().collect::>(); + let (rows, cols) = (primes.len(), LIMIT + 1); + let mut ways = vec![ + std::iter::once(1) + .chain(std::iter::repeat(0).take(cols - 1)) + .collect::>(); + rows + ]; + + // Bottom-up dynamic programming. + for sum in 1..cols { + ways[0][sum] = if sum % primes[0] as usize == 0 { 1 } else { 0 }; + } + for idx in 1..rows { + for sum in 1..cols { + ways[idx][sum] = ways[idx - 1][sum] + + if sum >= primes[idx] as usize { + ways[idx][sum - primes[idx] as usize] + } else { + 0 + }; + } + } + let result = ways[rows - 1] + .iter() + .enumerate() + .find(|(_, &count)| count >= 5000) + .unwrap() + .0; + + result as i64 +}