From 2104fa7aebe8d76b2b2b2c47fe7e2ee615a05df6 Mon Sep 17 00:00:00 2001 From: Nikos Giachoudis Date: Wed, 14 Sep 2022 11:40:04 +0300 Subject: [PATCH] Unify `O(sqrt(N))` `is_prime` functions under `project_euler` (#6258) * fixes #5434 * fixes broken solution * removes assert * removes assert * Apply suggestions from code review Co-authored-by: John Law * Update project_euler/problem_003/sol1.py Co-authored-by: John Law --- project_euler/problem_003/sol1.py | 30 +++++++++--------- project_euler/problem_007/sol1.py | 32 +++++++++++-------- project_euler/problem_007/sol2.py | 31 ++++++++++++++----- project_euler/problem_007/sol3.py | 31 ++++++++++++++----- project_euler/problem_010/sol1.py | 27 +++++++++++----- project_euler/problem_010/sol2.py | 23 +++++++++++--- project_euler/problem_027/sol1.py | 43 ++++++++++++++++++-------- project_euler/problem_037/sol1.py | 51 ++++++++++++++++++++++--------- project_euler/problem_041/sol1.py | 40 ++++++++++++++++++------ project_euler/problem_046/sol1.py | 49 ++++++++++++++++++++--------- project_euler/problem_049/sol1.py | 40 ++++++++++++++++-------- project_euler/problem_058/sol1.py | 51 ++++++++++++++++++++----------- 12 files changed, 313 insertions(+), 135 deletions(-) diff --git a/project_euler/problem_003/sol1.py b/project_euler/problem_003/sol1.py index 606a6945e..a7d01bb04 100644 --- a/project_euler/problem_003/sol1.py +++ b/project_euler/problem_003/sol1.py @@ -13,9 +13,11 @@ References: import math -def is_prime(num: int) -> bool: - """ - Returns boolean representing primality of given number num. +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -26,23 +28,21 @@ def is_prime(num: int) -> bool: >>> is_prime(2999) True >>> is_prime(0) - Traceback (most recent call last): - ... - ValueError: Parameter num must be greater than or equal to two. + False >>> is_prime(1) - Traceback (most recent call last): - ... - ValueError: Parameter num must be greater than or equal to two. + False """ - if num <= 1: - raise ValueError("Parameter num must be greater than or equal to two.") - if num == 2: + if 1 < number < 4: + # 2 and 3 are primes return True - elif num % 2 == 0: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(3, int(math.sqrt(num)) + 1, 2): - if num % i == 0: + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_007/sol1.py b/project_euler/problem_007/sol1.py index 78fbcb511..f52ff931f 100644 --- a/project_euler/problem_007/sol1.py +++ b/project_euler/problem_007/sol1.py @@ -15,29 +15,37 @@ References: from math import sqrt -def is_prime(num: int) -> bool: - """ - Determines whether the given number is prime or not +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) + >>> is_prime(3) + True + >>> is_prime(27) False - >>> is_prime(29) + >>> is_prime(2999) True >>> is_prime(0) False + >>> is_prime(1) + False """ - if num == 2: + if 1 < number < 4: + # 2 and 3 are primes return True - elif num % 2 == 0: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - else: - sq = int(sqrt(num)) + 1 - for i in range(3, sq, 2): - if num % i == 0: - return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False return True diff --git a/project_euler/problem_007/sol2.py b/project_euler/problem_007/sol2.py index 44d72e949..75d351889 100644 --- a/project_euler/problem_007/sol2.py +++ b/project_euler/problem_007/sol2.py @@ -11,22 +11,39 @@ What is the 10001st prime number? References: - https://en.wikipedia.org/wiki/Prime_number """ +import math def is_prime(number: int) -> bool: - """ - Determines whether the given number is prime or not + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) - False - >>> is_prime(29) + >>> is_prime(3) True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - for i in range(2, int(number**0.5) + 1): - if number % i == 0: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_007/sol3.py b/project_euler/problem_007/sol3.py index daa719cef..774260db9 100644 --- a/project_euler/problem_007/sol3.py +++ b/project_euler/problem_007/sol3.py @@ -16,20 +16,37 @@ import math def is_prime(number: int) -> bool: - """ - Determines whether a given number is prime or not + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True - >>> is_prime(15) - False - >>> is_prime(29) + >>> is_prime(3) True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if number % 2 == 0 and number > 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return all(number % i for i in range(3, int(math.sqrt(number)) + 1, 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def prime_generator(): diff --git a/project_euler/problem_010/sol1.py b/project_euler/problem_010/sol1.py index e060761ee..31f2feda3 100644 --- a/project_euler/problem_010/sol1.py +++ b/project_euler/problem_010/sol1.py @@ -11,12 +11,14 @@ References: - https://en.wikipedia.org/wiki/Prime_number """ -from math import sqrt +import math -def is_prime(n: int) -> bool: - """ - Returns boolean representing primality of given number num. +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -26,13 +28,24 @@ def is_prime(n: int) -> bool: False >>> is_prime(2999) True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if 1 < n < 4: + if 1 < number < 4: + # 2 and 3 are primes return True - elif n < 2 or not n % 2: + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return not any(not n % i for i in range(3, int(sqrt(n) + 1), 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def solution(n: int = 2000000) -> int: diff --git a/project_euler/problem_010/sol2.py b/project_euler/problem_010/sol2.py index a288bb85f..245cca1d1 100644 --- a/project_euler/problem_010/sol2.py +++ b/project_euler/problem_010/sol2.py @@ -16,8 +16,10 @@ from itertools import takewhile def is_prime(number: int) -> bool: - """ - Returns boolean representing primality of given number num. + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). >>> is_prime(2) True @@ -27,11 +29,24 @@ def is_prime(number: int) -> bool: False >>> is_prime(2999) True + >>> is_prime(0) + False + >>> is_prime(1) + False """ - if number % 2 == 0 and number > 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - return all(number % i for i in range(3, int(math.sqrt(number)) + 1, 2)) + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def prime_generator() -> Iterator[int]: diff --git a/project_euler/problem_027/sol1.py b/project_euler/problem_027/sol1.py index 928c0ec4f..c93e2b4fa 100644 --- a/project_euler/problem_027/sol1.py +++ b/project_euler/problem_027/sol1.py @@ -23,22 +23,39 @@ n = 0. import math -def is_prime(k: int) -> bool: - """ - Determine if a number is prime - >>> is_prime(10) - False - >>> is_prime(11) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + A number is prime if it has exactly two factors: 1 and itself. + Returns boolean representing primality of given number num (i.e., if the + result is true, then the number is indeed prime else it is not). + + >>> is_prime(2) True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(2999) + True + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(-10) + False """ - if k < 2 or k % 2 == 0: - return False - elif k == 2: + + if 1 < number < 4: + # 2 and 3 are primes return True - else: - for x in range(3, int(math.sqrt(k) + 1), 2): - if k % x == 0: - return False + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False return True diff --git a/project_euler/problem_037/sol1.py b/project_euler/problem_037/sol1.py index 0411ad41b..ef7686cbc 100644 --- a/project_euler/problem_037/sol1.py +++ b/project_euler/problem_037/sol1.py @@ -1,4 +1,7 @@ """ +Truncatable primes +Problem 37: https://projecteuler.net/problem=37 + The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3. @@ -11,28 +14,46 @@ NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. from __future__ import annotations -seive = [True] * 1000001 -seive[1] = False -i = 2 -while i * i <= 1000000: - if seive[i]: - for j in range(i * i, 1000001, i): - seive[j] = False - i += 1 +import math -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise, for 1 <= n <= 1000000 - >>> is_prime(87) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) False >>> is_prime(1) False - >>> is_prime(25363) + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - return seive[n] + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def list_truncated_nums(n: int) -> list[int]: diff --git a/project_euler/problem_041/sol1.py b/project_euler/problem_041/sol1.py index 80ef2125b..2ef012068 100644 --- a/project_euler/problem_041/sol1.py +++ b/project_euler/problem_041/sol1.py @@ -12,25 +12,45 @@ pandigital prime. """ from __future__ import annotations +import math from itertools import permutations -from math import sqrt -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise. - >>> is_prime(67483) +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) False >>> is_prime(563) True - >>> is_prime(87) + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - if n % 2 == 0: + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(3, int(sqrt(n) + 1), 2): - if n % i == 0: + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False return True diff --git a/project_euler/problem_046/sol1.py b/project_euler/problem_046/sol1.py index 550c4c7c4..07dd9bbf8 100644 --- a/project_euler/problem_046/sol1.py +++ b/project_euler/problem_046/sol1.py @@ -19,30 +19,49 @@ prime and twice a square? from __future__ import annotations -seive = [True] * 100001 -i = 2 -while i * i <= 100000: - if seive[i]: - for j in range(i * i, 100001, i): - seive[j] = False - i += 1 +import math -def is_prime(n: int) -> bool: - """ - Returns True if n is prime, - False otherwise, for 2 <= n <= 100000 +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False + >>> is_prime(1) + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False >>> is_prime(87) False - >>> is_prime(23) + >>> is_prime(563) True - >>> is_prime(25363) + >>> is_prime(2999) + True + >>> is_prime(67483) False """ - return seive[n] + + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False + + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True -odd_composites = [num for num in range(3, len(seive), 2) if not is_prime(num)] +odd_composites = [num for num in range(3, 100001, 2) if not is_prime(num)] def compute_nums(n: int) -> list[int]: diff --git a/project_euler/problem_049/sol1.py b/project_euler/problem_049/sol1.py index dd2ef71a3..5c7560cbd 100644 --- a/project_euler/problem_049/sol1.py +++ b/project_euler/problem_049/sol1.py @@ -25,32 +25,46 @@ After that, bruteforce all passed candidates sequences using The bruteforce of this solution will be about 1 sec. """ +import math from itertools import permutations -from math import floor, sqrt def is_prime(number: int) -> bool: - """ - function to check whether the number is prime or not. - >>> is_prime(2) - True - >>> is_prime(6) + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) False >>> is_prime(1) False - >>> is_prime(-800) - False - >>> is_prime(104729) + >>> is_prime(2) True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) + False """ - if number < 2: + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes return False - for i in range(2, floor(sqrt(number)) + 1): - if number % i == 0: + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: return False - return True diff --git a/project_euler/problem_058/sol1.py b/project_euler/problem_058/sol1.py index c59b0dd71..6a991c58b 100644 --- a/project_euler/problem_058/sol1.py +++ b/project_euler/problem_058/sol1.py @@ -33,29 +33,46 @@ So we check individually each one of these before incrementing our count of current primes. """ -from math import isqrt +import math -def is_prime(number: int) -> int: - """ - Returns whether the given number is prime or not +def is_prime(number: int) -> bool: + """Checks to see if a number is a prime in O(sqrt(n)). + + A number is prime if it has exactly two factors: 1 and itself. + + >>> is_prime(0) + False >>> is_prime(1) - 0 - >>> is_prime(17) - 1 - >>> is_prime(10000) - 0 + False + >>> is_prime(2) + True + >>> is_prime(3) + True + >>> is_prime(27) + False + >>> is_prime(87) + False + >>> is_prime(563) + True + >>> is_prime(2999) + True + >>> is_prime(67483) + False """ - if number == 1: - return 0 - if number % 2 == 0 and number > 2: - return 0 + if 1 < number < 4: + # 2 and 3 are primes + return True + elif number < 2 or number % 2 == 0 or number % 3 == 0: + # Negatives, 0, 1, all even numbers, all multiples of 3 are not primes + return False - for i in range(3, isqrt(number) + 1, 2): - if number % i == 0: - return 0 - return 1 + # All primes number are in format of 6k +/- 1 + for i in range(5, int(math.sqrt(number) + 1), 6): + if number % i == 0 or number % (i + 2) == 0: + return False + return True def solution(ratio: float = 0.1) -> int: