HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Function to find two prime numbers that sum up to a given even number

Submitted by: @import:stackexchange-codereview··
0
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__

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:

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


Notice 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.