The prime factors of 13195 are 5, 7, 13 and 29.
What is the largest prime factor of the number 600851475143?
We start by writing a function which calculates all primes till a certain value using the Sieve of Eratosthenes.
def get_primes_smaller(number):
primes = []
prospects = [n for n in range(2, number)]
while prospects:
p = prospects[0]
prospects = [x for x in prospects if x % p != 0]
primes.append(p)
return primes
assert(get_primes_smaller(0) == [])
assert(get_primes_smaller(10) == [2, 3, 5, 7,])
Now we create a function which does prime factorization. It is very important that we only test primes smaller than the squre root. Otherwise the complexity becomes too big.
import math
def get_prime_factors(number):
possible_factors = get_primes_smaller(math.ceil(math.sqrt(number)))
remainder = number
factors = []
for p in possible_factors:
while remainder % p == 0:
remainder /= p
factors.append(p)
if remainder == 1:
break
if remainder != 1:
factors.append(remainder)
return factors
assert(get_prime_factors(7) == [7])
assert(get_prime_factors(12) == [2, 2, 3])
assert(get_prime_factors(88) == [2, 2, 2, 11])
assert(get_prime_factors(13195) == [5, 7, 13, 29])
Now we can go ahead an brute force the solution.
def get_largest_prime(number):
return get_prime_factors(number)[-1]
assert(get_largest_prime(13195) == 29)
#print(get_largest_prime(600851475143))
print(6857) # computed the previously but remove it so that we can reexecute the complete kernel
Okay, actually we can brute force, but it is really slow. A better solution is to write a prime number generator which calculates the next number on demand.
def is_prime(n, smaller_primes):
for s in smaller_primes:
if n % s == 0:
return False
if s * s > n:
return True
return True
def prime_generator_function():
primes = [2, 3, 5, 7]
for p in primes:
yield p
while True:
p += 2
if is_prime(p, primes):
primes.append(p)
yield p
def get_prime_factors(number):
prime_generator = prime_generator_function()
remainder = number
factors = []
for p in prime_generator:
while remainder % p == 0:
remainder /= p
factors.append(p)
if remainder == 1 or p * p > number:
break
if remainder != 1:
factors.append(remainder)
return factors
print(get_largest_prime(600851475143))
Here we go. Obviously much better than precalculation primes that we never need.