patternpythonMinor
Function to find two prime numbers that sum up to a given even number
Viewed 0 times
sumnumbernumbersfunctiontwothatfindevenprimegiven
Problem
The Goldbach Conjecture asserts that any even number over 2 will be the sum of exactly two prime numbers. I've created a function to find two prime numbers that add up to the number entered, but would like some help streamlining it and making it more robust. One thing I would like to add is the ability to find all prime pairs that add up to the given number and append them as tuples to a list and return it. I have a separate function that will find all prime numbers lower than or equal to a given number.
```
def goldbach_conj(number):
x, y = 0, 0
result = 0
if not number % 2:
prime_list = list_of_primes(number)
while result != number:
for i in range(len(prime_list)):
x = prime_list[i]
if result == number: break
for j in range(len(prime_list)):
y = prime_list[j]
result = x + y
print("Adding {} and {}.".format(x, y))
print("Result is {}".format(result))
if result == number: break
return x, y
def is_prime(number):
if number % 2:
# equivalent to if number % 2 != 0 because if number is
# divisible by 2 it will return 0, evaluating as 'False'.
for num in range(3, int(math.sqrt(number)) + 1, 2):
if number % num == 0:
return False
return True
else:
return False
def list_of_primes(number):
prime_list = []
for x in range(2, number + 1):
if is_prime(x):
prime_list.append(x)
return prime_list
def main():
while True:
usr_in = eval(input("Please enter a positive number"
" greater than 1: "))
if usr_in > 1: break
else:
print("Number not valid.")
prime_list = goldbach_conj(usr_in)
print(prime_list)
# prime_list = list_of_primes(usr_in)
# for x in prime_list:
# print(x)
if __name__
```
def goldbach_conj(number):
x, y = 0, 0
result = 0
if not number % 2:
prime_list = list_of_primes(number)
while result != number:
for i in range(len(prime_list)):
x = prime_list[i]
if result == number: break
for j in range(len(prime_list)):
y = prime_list[j]
result = x + y
print("Adding {} and {}.".format(x, y))
print("Result is {}".format(result))
if result == number: break
return x, y
def is_prime(number):
if number % 2:
# equivalent to if number % 2 != 0 because if number is
# divisible by 2 it will return 0, evaluating as 'False'.
for num in range(3, int(math.sqrt(number)) + 1, 2):
if number % num == 0:
return False
return True
else:
return False
def list_of_primes(number):
prime_list = []
for x in range(2, number + 1):
if is_prime(x):
prime_list.append(x)
return prime_list
def main():
while True:
usr_in = eval(input("Please enter a positive number"
" greater than 1: "))
if usr_in > 1: break
else:
print("Number not valid.")
prime_list = goldbach_conj(usr_in)
print(prime_list)
# prime_list = list_of_primes(usr_in)
# for x in prime_list:
# print(x)
if __name__
Solution
You are doing an \$O(n^2)\$ search over a sorted list, which very often implies an affirmative answer to the infamous "can we do better?" question. For this particular problem, you can get \$O(n)\$ performance by simultaneously scanning from the front and back of the list of primes:
Notice that, since generating all primes below
A sample run:
def prime_sieve(n):
# returns all primes smaller than n
sieve = [True] * n
sieve[:2] = [False, False] # 0 and 1 are not primes
primes = []
for prime, is_prime in enumerate(sieve):
if not is_prime:
continue
primes.append(prime)
for not_prime in range(prime*prime, n, prime):
sieve[not_prime] = False
return primes
def sum_of_primes(value):
primes = prime_sieve(value)
lo = 0
hi = len(primes) - 1
while lo <= hi:
prime_sum = primes[lo] + primes[hi]
if prime_sum < value:
lo += 1
else:
if prime_sum == value:
yield primes[lo], primes[hi]
hi -= 1Notice that, since generating all primes below
n can be done in \$O(n \log \log n)\$ time, it is now the prime generation that dominates the total time, i.e. using this faster algorithm makes finding the pairs virtually free (when compared to finding the primes themselves).A sample run:
>>> list(sum_of_primes(42))
[(5, 37), (11, 31), (13, 29), (19, 23)]Code Snippets
def prime_sieve(n):
# returns all primes smaller than n
sieve = [True] * n
sieve[:2] = [False, False] # 0 and 1 are not primes
primes = []
for prime, is_prime in enumerate(sieve):
if not is_prime:
continue
primes.append(prime)
for not_prime in range(prime*prime, n, prime):
sieve[not_prime] = False
return primes
def sum_of_primes(value):
primes = prime_sieve(value)
lo = 0
hi = len(primes) - 1
while lo <= hi:
prime_sum = primes[lo] + primes[hi]
if prime_sum < value:
lo += 1
else:
if prime_sum == value:
yield primes[lo], primes[hi]
hi -= 1>>> list(sum_of_primes(42))
[(5, 37), (11, 31), (13, 29), (19, 23)]Context
StackExchange Code Review Q#99161, answer score: 6
Revisions (0)
No revisions yet.