mirror of
https://github.com/jlengrand/project_euler.git
synced 2026-03-10 08:41:20 +00:00
Downloaded some new stuff on primes. Signed-off-by: Julien Lengrand-Lambert <julien@lengrand.fr>
98 lines
3.1 KiB
Python
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
|
|
''' |