Files
project_euler/utils/primes.py
Julien Lengrand-Lambert 98d0e588d8 Problem 3 more efficient.
Downloaded some new stuff on primes. 

Signed-off-by: Julien Lengrand-Lambert <julien@lengrand.fr>
2012-02-21 20:40:57 +01:00

98 lines
3.1 KiB
Python

'''
Created on
@author: .s-anand
@contact: http://www.s-anand.net/euler.html
Stolen from http://www.s-anand.net/euler.html
'''
prime_list = [2, 3, 5, 7, 11, 13, 17, 19, 23] # Ensure that this is initialised with at least 1 prime
prime_dict = dict.fromkeys(prime_list, 1)
lastn = prime_list[-1]
def _isprime(n):
''' Raw check to see if n is prime. Assumes that prime_list is already populated '''
isprime = n >= 2 and 1 or 0
for prime in prime_list: # Check for factors with all primes
if prime * prime > n: break # ... up to sqrt(n)
if not n % prime:
isprime = 0
break
if isprime: prime_dict[n] = 1 # Maintain a dictionary for fast lookup
return isprime
def _refresh(x):
''' Refreshes primes upto x '''
global lastn
while lastn <= x: # Keep working until we've got up to x
lastn = lastn + 1 # Check the next number
if _isprime(lastn):
prime_list.append(lastn) # Maintain a list for sequential access
def prime(x):
''' Returns the xth prime '''
global lastn
while len(prime_list) <= x: # Keep working until we've got the xth prime
lastn = lastn + 1 # Check the next number
if _isprime(lastn):
prime_list.append(lastn) # Maintain a list for sequential access
return prime_list[x]
def isprime(x):
''' Returns 1 if x is prime, 0 if not. Uses a pre-computed dictionary '''
_refresh(x) # Compute primes up to x (which is a bit wasteful)
return prime_dict.get(x, 0) # Check if x is in the list
def factors(n):
''' Returns a prime factors of n as a list '''
_refresh(n)
x, xp, f = 0, prime_list[0], []
while xp <= n:
if not n % xp:
f.append(xp)
n = n / xp
else:
x = x + 1
xp = prime_list[x]
return f
def all_factors(n):
''' Returns all factors of n, including 1 and n '''
f = factors(n)
elts = sorted(set(f))
numelts = len(elts)
def gen_inner(i):
if i >= numelts:
yield 1
return
thiselt = elts[i]
thismax = f.count(thiselt)
powers = [1]
for j in xrange(thismax):
powers.append(powers[-1] * thiselt)
for d in gen_inner(i+1):
for prime_power in powers:
yield prime_power * d
for d in gen_inner(0):
yield d
def num_factors(n):
''' Returns the number of factors of n, including 1 and n '''
div = 1
x = 0
while n > 1:
c = 1
while not n % prime(x):
c = c + 1
n = n / prime(x)
x = x + 1
div = div * c
return div
'''
Optimisation notes:
# Function access FAIRLY slower than Array access is SLIGHTLY slower than local variable access
# Generators are SLIGHTLY slower than returning a list
# Dictionary access takes ZERO time
'''