|
| 1 | +# <https://projecteuler.net/problem=88> |
| 2 | +# <p>A natural number, $N$, that can be written as the sum and product of a given set of at least two natural numbers, $\{a_1, a_2, \dots, a_k\}$ is called a product-sum number: $N = a_1 + a_2 + \cdots + a_k = a_1 \times a_2 \times \cdots \times a_k$.</p> |
| 3 | +# <p>For example, $6 = 1 + 2 + 3 = 1 \times 2 \times 3$.</p> |
| 4 | +# <p>For a given set of size, $k$, we shall call the smallest $N$ with this property a minimal product-sum number. The minimal product-sum numbers for sets of size, $k = 2, 3, 4, 5$, and $6$ are as follows.</p> |
| 5 | +# <ul style="list-style-type:none;"> |
| 6 | +# <li>$k=2$: $4 = 2 \times 2 = 2 + 2$</li> |
| 7 | +# <li>$k=3$: $6 = 1 \times 2 \times 3 = 1 + 2 + 3$</li> |
| 8 | +# <li>$k=4$: $8 = 1 \times 1 \times 2 \times 4 = 1 + 1 + 2 + 4$</li> |
| 9 | +# <li>$k=5$: $8 = 1 \times 1 \times 2 \times 2 \times 2 = 1 + 1 + 2 + 2 + 2$</li> |
| 10 | +# <li>$k=6$: $12 = 1 \times 1 \times 1 \times 1 \times 2 \times 6 = 1 + 1 + 1 + 1 + 2 + 6$</li></ul> |
| 11 | +# <p>Hence for $2 \le k \le 6$, the sum of all the minimal product-sum numbers is $4+6+8+12 = 30$; note that $8$ is only counted once in the sum.</p> |
| 12 | +# <p>In fact, as the complete set of minimal product-sum numbers for $2 \le k \le 12$ is $\{4, 6, 8, 12, 15, 16\}$, the sum is $61$.</p> |
| 13 | +# <p>What is the sum of all the minimal product-sum numbers for $2 \le k \le 12000$?</p> |
| 14 | +# |
| 15 | +# Notes: |
| 16 | +# - https://www.ivl-projecteuler.com/overview-of-problems/40-difficulty/problem-88 |
| 17 | +# - https://blog.dreamshire.com/project-euler-88-solution/ |
| 18 | +# - https://docs.python.org/3/library/functools.html |
| 19 | +# - k is the length of the list of natural numbers which are multiplied and added |
| 20 | +# - N is the result of adding the list of natural numbers |
| 21 | +# - Number of Ones = Product of Factors - Sum of Factors |
| 22 | +# - k = Number of Ones + Number of Factors |
| 23 | +from operator import mul |
| 24 | +from functools import reduce |
| 25 | + |
| 26 | +def sum_of_minimal_product_sum_numbers(maxK): |
| 27 | + minProdSumNums = get_minimal_product_sum_numbers(maxK) |
| 28 | + return sum(set(minProdSumNums.values())) |
| 29 | + |
| 30 | +def test_example_case(): |
| 31 | + assert 30 == sum_of_minimal_product_sum_numbers(6) |
| 32 | + |
| 33 | +def test_real_k_case(): |
| 34 | + # assert 890 == sum_of_minimal_product_sum_numbers(60) |
| 35 | + # assert 39072 == sum_of_minimal_product_sum_numbers(600) |
| 36 | + # assert 93063 == sum_of_minimal_product_sum_numbers(1000) |
| 37 | + assert 7587457 == sum_of_minimal_product_sum_numbers(12000) |
| 38 | + |
| 39 | +def get_minimal_product_sum_numbers(maxK, oldFactors = [], minProdSumNums = {}): |
| 40 | + if len(oldFactors) > 12: |
| 41 | + return minProdSumNums |
| 42 | + start = get_largest_factor(oldFactors) or 2 |
| 43 | + for i in range(start, maxK + 1): |
| 44 | + factors = oldFactors + [i] |
| 45 | + N = reduce(mul, factors, 1) |
| 46 | + K = k(N, factors) |
| 47 | + if K > maxK: |
| 48 | + break |
| 49 | + if K > 1 and N < minProdSumNums.get(K, N + 1): |
| 50 | + minProdSumNums[K] = N |
| 51 | + minProdSumNums = get_minimal_product_sum_numbers(maxK, factors, minProdSumNums) |
| 52 | + return minProdSumNums |
| 53 | + |
| 54 | +def test_getting_minimal_product_sum_numbers_works(): |
| 55 | + assert {2:4, 3:6} == get_minimal_product_sum_numbers(3, [], {}) |
| 56 | + |
| 57 | +def get_largest_factor(sortedFactorList): |
| 58 | + return sortedFactorList[-1] if sortedFactorList else None |
| 59 | + |
| 60 | +def k(N, factors): |
| 61 | + return len(factors) + number_of_ones(N, factors) |
| 62 | + |
| 63 | +def test_k(): |
| 64 | + assert 2 == k(4, [2, 2]) |
| 65 | + assert 3 == k(6, [2, 3]) |
| 66 | + |
| 67 | +def number_of_ones(N, factors): |
| 68 | + return N - sum(factors) |
| 69 | + |
| 70 | +def test_number_of_ones(): |
| 71 | + assert 0 == number_of_ones(4, [2, 2]) |
| 72 | + assert 1 == number_of_ones(6, [2, 3]) |
0 commit comments