From e54104513376c8ed3a130baa857f2d1599e708dd Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 18:29:56 +0530 Subject: [PATCH 01/10] Implemented improved algorithm using Numba for Project Euler Problem 73 Existing file with a Python solution to count fractions between 1/3 and 1/2 for denominators up to 12,000 using nested loops and the math module's gcd function. This approach iterates through all possible fractions and counts those meeting the specified criteria. Added an improved solution utilizing the Numba library for optimized performance. This implementation uses a Numba-optimized function solution decorated with @njit to compile the code to machine code, significantly improving execution speed. The algorithm employs a different approach to count fractions between 1/3 and 1/2. It utilizes a loop with numerator and denominator ranges to calculate the count, avoiding unnecessary iterations by counting the fractions directly meeting the criteria while leveraging Numba's JIT compilation for efficiency. Fixes #8594 --- project_euler/problem_073/sol2.py | 60 +++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 project_euler/problem_073/sol2.py diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py new file mode 100644 index 000000000000..f3b0ab9921d5 --- /dev/null +++ b/project_euler/problem_073/sol2.py @@ -0,0 +1,60 @@ +""" +Project Euler Problem 73: https://projecteuler.net/problem=73 + +Consider the fraction, n/d, where n and d are positive integers. +If n int: + """ + Returns the number of fractions lying between 1/3 and 1/2 + in the sorted set of reduced proper fractions for d ≤ limit. + + Args: + - limit (int): The maximum denominator value. + + Returns: + - int: Number of fractions between 1/3 and 1/2. + + Example: + >>> count_fractions(4) + 0 + >>> count_fractions(5) + 1 + >>> count_fractions(8) + 3 + """ + + count = 0 + + for denominator in range(2, limit + 1): + lower_limit = denominator // 3 + 1 + upper_limit = (denominator - 1) // 2 + divisors = 0 + + for numerator in range(lower_limit, upper_limit + 1): + if gcd(numerator, denominator) != 1: + divisors += 1 + + count += upper_limit - lower_limit + 1 - divisors + + return count + + +if __name__ == "__main__": + print(f"{solution() = }") From 3f00dbd50962ab4caa30b332f2c4e06d263509d0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:10:11 +0000 Subject: [PATCH 02/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- project_euler/problem_073/sol2.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index f3b0ab9921d5..6138e3f92867 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -19,8 +19,9 @@ from numba import njit from math import gcd + @njit -def solution(limit: int=12_000) -> int: +def solution(limit: int = 12_000) -> int: """ Returns the number of fractions lying between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ limit. From 8d6ab30ebbf3f35c1afffcdc288fd0dbc9d2a192 Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 18:47:21 +0530 Subject: [PATCH 03/10] Added code to install Numba automatically when code is run. --- project_euler/problem_073/sol2.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index f3b0ab9921d5..bfd7ff2d38e3 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -15,7 +15,14 @@ How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? """ - +import subprocess + +# Attempt to install 'numba' using pip +try: + subprocess.run(["pip", "install", "numba"]) + print("Numba installed successfully!") +except Exception as e: + print(f"Error installing numba: {e}") from numba import njit from math import gcd From 52acb90581790fe85e718f1c00965c585d2d6d0a Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 18:59:34 +0530 Subject: [PATCH 04/10] Changed the code to not use Numba, since that created issues during pytest. This program still performs significantly faster than existing solution. Fixes #8594 --- project_euler/problem_073/sol2.py | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index 231e36798dc5..c80b79caa862 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -15,19 +15,7 @@ How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? """ -import subprocess - -# Attempt to install 'numba' using pip -try: - subprocess.run(["pip", "install", "numba"]) - print("Numba installed successfully!") -except Exception as e: - print(f"Error installing numba: {e}") -from numba import njit from math import gcd - - -@njit def solution(limit: int = 12_000) -> int: """ Returns the number of fractions lying between 1/3 and 1/2 @@ -47,22 +35,17 @@ def solution(limit: int = 12_000) -> int: >>> count_fractions(8) 3 """ - + phi = [i for i in range(limit + 1)] count = 0 - for denominator in range(2, limit + 1): - lower_limit = denominator // 3 + 1 - upper_limit = (denominator - 1) // 2 - divisors = 0 - - for numerator in range(lower_limit, upper_limit + 1): - if gcd(numerator, denominator) != 1: - divisors += 1 + for d in range(2, limit + 1): + if phi[d] == d: + for j in range(d, limit + 1, d): + phi[j] -= phi[j] // d - count += upper_limit - lower_limit + 1 - divisors + count += phi[d] // 2 - phi[(d + 2) // 3] return count - if __name__ == "__main__": print(f"{solution() = }") From 1278112cf9ce97fe10adff573454dc44294fa5d7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:30:55 +0000 Subject: [PATCH 05/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- project_euler/problem_073/sol2.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index c80b79caa862..7f254b67919f 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -16,6 +16,8 @@ of reduced proper fractions for d ≤ 12,000? """ from math import gcd + + def solution(limit: int = 12_000) -> int: """ Returns the number of fractions lying between 1/3 and 1/2 @@ -47,5 +49,6 @@ def solution(limit: int = 12_000) -> int: return count + if __name__ == "__main__": print(f"{solution() = }") From 8f11b8ccfd44e1a57f028e37bd288d8287c524c6 Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 19:02:00 +0530 Subject: [PATCH 06/10] Corrected mistakes with naming. --- project_euler/problem_073/sol2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index c80b79caa862..4970083e5982 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -28,11 +28,11 @@ def solution(limit: int = 12_000) -> int: - int: Number of fractions between 1/3 and 1/2. Example: - >>> count_fractions(4) + >>> solution(4) 0 - >>> count_fractions(5) + >>> solution(5) 1 - >>> count_fractions(8) + >>> solution(8) 3 """ phi = [i for i in range(limit + 1)] From e965f3b019850de94ebd10d7cb56439eb27ac839 Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 19:07:35 +0530 Subject: [PATCH 07/10] Removed unused math module, replaced a list comprehension with list(). --- project_euler/problem_073/sol2.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index 5a8dbe5be967..e6f1740bf90c 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -15,7 +15,6 @@ How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? """ -from math import gcd def solution(limit: int = 12_000) -> int: @@ -37,7 +36,7 @@ def solution(limit: int = 12_000) -> int: >>> solution(8) 3 """ - phi = [i for i in range(limit + 1)] + phi = list(range(limit + 1)) count = 0 for d in range(2, limit + 1): From a4aca0110a000a725b67cc761560ce877d2e4b27 Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 19:11:06 +0530 Subject: [PATCH 08/10] Updated doctring explaining solution function. --- project_euler/problem_073/sol2.py | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index e6f1740bf90c..1898764730dc 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -18,21 +18,16 @@ def solution(limit: int = 12_000) -> int: - """ - Returns the number of fractions lying between 1/3 and 1/2 - in the sorted set of reduced proper fractions for d ≤ limit. - - Args: - - limit (int): The maximum denominator value. - - Returns: - - int: Number of fractions between 1/3 and 1/2. + """ + Returns number of fractions lie between 1/3 and 1/2 in the sorted set + of reduced proper fractions for d ≤ max_d - Example: >>> solution(4) 0 + >>> solution(5) 1 + >>> solution(8) 3 """ From 4d99dab484f43df849a5b97b715febd4ce8bf787 Mon Sep 17 00:00:00 2001 From: Anumaneni Venkat Balachandra Date: Thu, 7 Dec 2023 19:15:09 +0530 Subject: [PATCH 09/10] Fixed indentation. --- project_euler/problem_073/sol2.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index 1898764730dc..231d376f6497 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -15,10 +15,8 @@ How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? """ - - def solution(limit: int = 12_000) -> int: - """ + """ Returns number of fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ max_d @@ -46,3 +44,5 @@ def solution(limit: int = 12_000) -> int: if __name__ == "__main__": print(f"{solution() = }") + + From 95a73319639bf88bd7436f8c0bf6930ea182ab38 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 7 Dec 2023 13:47:03 +0000 Subject: [PATCH 10/10] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- project_euler/problem_073/sol2.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/project_euler/problem_073/sol2.py b/project_euler/problem_073/sol2.py index 231d376f6497..2272c48ba0dc 100644 --- a/project_euler/problem_073/sol2.py +++ b/project_euler/problem_073/sol2.py @@ -15,6 +15,8 @@ How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? """ + + def solution(limit: int = 12_000) -> int: """ Returns number of fractions lie between 1/3 and 1/2 in the sorted set @@ -44,5 +46,3 @@ def solution(limit: int = 12_000) -> int: if __name__ == "__main__": print(f"{solution() = }") - -