From 99adac0eb135ab9e48e86db01da520eded2f985a Mon Sep 17 00:00:00 2001 From: PetitNigaud <44503597+PetitNigaud@users.noreply.github.com> Date: Thu, 29 Oct 2020 08:04:42 +0100 Subject: [PATCH] Add first solution for Project Euler Problem 207 (#3522) * add solution to Project Euler problem 206 * Add solution to Project Euler problem 205 * updating DIRECTORY.md * updating DIRECTORY.md * Revert "Add solution to Project Euler problem 205" This reverts commit 64e3d36cab2b68630b73a217c9ba455202d85cbb. * Revert "add solution to Project Euler problem 206" This reverts commit 53568cf4efd84f4b1c039eade335655842fa29e3. * add solution for project euler problem 207 * updating DIRECTORY.md * add type hint for output of helper function * Correct default parameter value in solution * use descriptive variable names and remove problem solution from doctest Fixes: #2695 Co-authored-by: nico Co-authored-by: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> --- DIRECTORY.md | 2 + project_euler/problem_207/__init__.py | 0 project_euler/problem_207/sol1.py | 98 +++++++++++++++++++++++++++ 3 files changed, 100 insertions(+) create mode 100644 project_euler/problem_207/__init__.py create mode 100644 project_euler/problem_207/sol1.py diff --git a/DIRECTORY.md b/DIRECTORY.md index c3b32b1ab..9e8981f5f 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -720,6 +720,8 @@ * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_174/sol1.py) * Problem 191 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_191/sol1.py) + * Problem 207 + * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_207/sol1.py) * Problem 234 * [Sol1](https://github.com/TheAlgorithms/Python/blob/master/project_euler/problem_234/sol1.py) * Problem 551 diff --git a/project_euler/problem_207/__init__.py b/project_euler/problem_207/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/project_euler/problem_207/sol1.py b/project_euler/problem_207/sol1.py new file mode 100644 index 000000000..fb901fde1 --- /dev/null +++ b/project_euler/problem_207/sol1.py @@ -0,0 +1,98 @@ +""" + +Project Euler Problem 207: https://projecteuler.net/problem=207 + +Problem Statement: +For some positive integers k, there exists an integer partition of the form +4**t = 2**t + k, where 4**t, 2**t, and k are all positive integers and t is a real +number. The first two such partitions are 4**1 = 2**1 + 2 and +4**1.5849625... = 2**1.5849625... + 6. +Partitions where t is also an integer are called perfect. +For any m ≥ 1 let P(m) be the proportion of such partitions that are perfect with +k ≤ m. +Thus P(6) = 1/2. +In the following table are listed some values of P(m) + + P(5) = 1/1 + P(10) = 1/2 + P(15) = 2/3 + P(20) = 1/2 + P(25) = 1/2 + P(30) = 2/5 + ... + P(180) = 1/4 + P(185) = 3/13 + +Find the smallest m for which P(m) < 1/12345 + +Solution: +Equation 4**t = 2**t + k solved for t gives: + t = log2(sqrt(4*k+1)/2 + 1/2) +For t to be real valued, sqrt(4*k+1) must be an integer which is implemented in +function check_t_real(k). For a perfect partition t must be an integer. +To speed up significantly the search for partitions, instead of incrementing k by one +per iteration, the next valid k is found by k = (i**2 - 1) / 4 with an integer i and +k has to be a positive integer. If this is the case a partition is found. The partition +is perfect if t os an integer. The integer i is increased with increment 1 until the +proportion perfect partitions / total partitions drops under the given value. + +""" + +import math + + +def check_partition_perfect(positive_integer: int) -> bool: + """ + + Check if t = f(positive_integer) = log2(sqrt(4*positive_integer+1)/2 + 1/2) is a + real number. + + >>> check_partition_perfect(2) + True + + >>> check_partition_perfect(6) + False + + """ + + exponent = math.log2(math.sqrt(4 * positive_integer + 1) / 2 + 1 / 2) + + return exponent == int(exponent) + + +def solution(max_proportion: float = 1 / 12345) -> int: + """ + Find m for which the proportion of perfect partitions to total partitions is lower + than max_proportion + + >>> solution(1) > 5 + True + + >>> solution(1/2) > 10 + True + + >>> solution(3 / 13) > 185 + True + + """ + + total_partitions = 0 + perfect_partitions = 0 + + integer = 3 + while True: + partition_candidate = (integer ** 2 - 1) / 4 + # if candidate is an integer, then there is a partition for k + if partition_candidate == int(partition_candidate): + partition_candidate = int(partition_candidate) + total_partitions += 1 + if check_partition_perfect(partition_candidate): + perfect_partitions += 1 + if perfect_partitions > 0: + if perfect_partitions / total_partitions < max_proportion: + return partition_candidate + integer += 1 + + +if __name__ == "__main__": + print(f"{solution() = }")