def main(): start = time() primeObject = ProjectEulerPrime() primeList = [2] # 2 is the only even prime. for i in xrange(3, LIMIT / 183, 2): # interesting pattern: # all primes will be in the range of numbers if primeObject.isPrime(i): # LIMIT / (number of prime terms in the series for LIMIT / 10 ) primeList.append(i) # so 10 = 10 / 1, 100 = 100 / 2, 1000 = 1000 / 6, 10000 = 10000 / 21, # 100000 = 100000 / 65, 1000000 = 1000000 / 183 and so on for at least 100M. maxPrime = 0 maxNumberOfPrimes = 0 for i in xrange(len(primeList)): currentPrimeSequence = [primeList[i]] currentSum = primeList[i] for j in xrange(i + 1, len(primeList)): currentSum += primeList[j] currentPrimeSequence.append(primeList[j]) if currentSum < LIMIT and primeObject.isPrime(currentSum): if len(currentPrimeSequence) > maxNumberOfPrimes: maxNumberOfPrimes = len(currentPrimeSequence) maxPrime = sum(currentPrimeSequence) elif currentSum >= LIMIT: break print "Longest number of sequential primes that sum to a prime: ", maxNumberOfPrimes print "Sum: ", maxPrime end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() solutionSet = set([]) squareList = [number ** 2 for number in xrange(2, int(LIMIT ** 0.5) + 1) if primeObject.isPrime(number)] cubeList = [number ** 3 for number in xrange(2, int(LIMIT ** (1./3)) + 1) if primeObject.isPrime(number)] fourthList = [number ** 4 for number in xrange(2, int(LIMIT ** (1./4)) + 1) if primeObject.isPrime(number)] for square in squareList: for cube in cubeList: if square + cube >= LIMIT: break for fourth in fourthList: resultingSum = square + cube + fourth if resultingSum >= LIMIT: break else: solutionSet.add(resultingSum) print "Number of sums formed from squared, cubed, and fourthed primes that are < ",LIMIT, " : ", len(solutionSet) end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() primeList = [2] # 2 is the only even prime. for i in xrange(3, LIMIT / 183, 2): # interesting pattern: # all primes will be in the range of numbers if primeObject.isPrime( i ): # LIMIT / (number of prime terms in the series for LIMIT / 10 ) primeList.append( i ) # so 10 = 10 / 1, 100 = 100 / 2, 1000 = 1000 / 6, 10000 = 10000 / 21, # 100000 = 100000 / 65, 1000000 = 1000000 / 183 and so on for at least 100M. maxPrime = 0 maxNumberOfPrimes = 0 for i in xrange(len(primeList)): currentPrimeSequence = [primeList[i]] currentSum = primeList[i] for j in xrange(i + 1, len(primeList)): currentSum += primeList[j] currentPrimeSequence.append(primeList[j]) if currentSum < LIMIT and primeObject.isPrime(currentSum): if len(currentPrimeSequence) > maxNumberOfPrimes: maxNumberOfPrimes = len(currentPrimeSequence) maxPrime = sum(currentPrimeSequence) elif currentSum >= LIMIT: break print "Longest number of sequential primes that sum to a prime: ", maxNumberOfPrimes print "Sum: ", maxPrime end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() minRatio = LIMIT minValue = LIMIT sqrtOfLimit = int(LIMIT ** 0.5) # since phi(n) = n - 1 when n == prime, phi(n) can't ever be a permutation of n. # the next best thing is a pair of primes. # since n / phi(n) means being as close to 1 as possible, look for numbers around sqrt(LIMIT) rangeToConsider = RANGE_INCREMENT while rangeToConsider < RANGE_LIMIT: for i in xrange(sqrtOfLimit - rangeToConsider, sqrtOfLimit, 1): if primeObject.isPrime(i): for j in xrange(sqrtOfLimit + rangeToConsider, sqrtOfLimit, -1): candidateProduct = i * j if candidateProduct > LIMIT: continue if primeObject.isPrime(j): phi = round(i * j * float(i - 1) / i * float(j - 1) / j, 0) if i * j / phi < minRatio: candidateCharList = [char for char in str(i * j)] phiCharList = [char for char in str(int(phi))] candidateCharList.sort() phiCharList.sort() if candidateCharList == phiCharList: minRatio = i * j / phi minValue = i * j rangeToConsider += RANGE_INCREMENT end = time() print "Value for which ratio is minimized: ", minValue print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() minRatio = LIMIT minValue = LIMIT sqrtOfLimit = int(LIMIT**0.5) # since phi(n) = n - 1 when n == prime, phi(n) can't ever be a permutation of n. # the next best thing is a pair of primes. # since n / phi(n) means being as close to 1 as possible, look for numbers around sqrt(LIMIT) rangeToConsider = RANGE_INCREMENT while rangeToConsider < RANGE_LIMIT: for i in xrange(sqrtOfLimit - rangeToConsider, sqrtOfLimit, 1): if primeObject.isPrime(i): for j in xrange(sqrtOfLimit + rangeToConsider, sqrtOfLimit, -1): candidateProduct = i * j if candidateProduct > LIMIT: continue if primeObject.isPrime(j): phi = round( i * j * float(i - 1) / i * float(j - 1) / j, 0) if i * j / phi < minRatio: candidateCharList = [char for char in str(i * j)] phiCharList = [char for char in str(int(phi))] candidateCharList.sort() phiCharList.sort() if candidateCharList == phiCharList: minRatio = i * j / phi minValue = i * j rangeToConsider += RANGE_INCREMENT end = time() print "Value for which ratio is minimized: ", minValue print "Runtime: ", end - start, " seconds."
def main(): ''' If you do the algebra, you find that: R(k) % n = 0 => R(k) = a * n, where a is a natural number. => (10 ** k - 1) / 9 = a * n => 10 ** k = 9 * a * n + 1 And so 10 ** k mod 9 * n == 1 You also see: (n - 1) = b * k, where b is a natural number. => (n - 1) % k == 0 ''' current = 91 # start at first composite example. p = ProjectEulerPrime() results = set() while len(results) < 25: # obviously, 10 ** i > (9 * current). # note that since current is odd, current - 1 is even. for i in xrange(int(log10(9 * current) + 1), int((current - 1) / 2.) + 1): if (current - 1) % i == 0 and 10 ** i % (9 * current) == 1: results.add(current) break while True: current += 2 if current % 5 == 0: continue # check for multiples of 5 if p.isPrime(current): continue # test for primality. break print "Sum: {}".format(sum(results))
def main(): start = time() primeObject = ProjectEulerPrime() # the question is actually asking for the output of the totient function # from 2 to the problem's LIMIT. phiList = [1 for number in xrange(LIMIT + 1)] # defaults. phiList[0] = 0 phiList[1] = 0 for i in xrange(2, LIMIT + 1): if primeObject.isPrime(i): phiList[i] = i - 1 for j in xrange(i * 2, len(phiList), i): phiList[j] *= float(i - 1) / i else: phiList[i] *= i print "Number of reduced, proper fractions where the denominator <= ", LIMIT, " : ", sum([int(round(number, 0)) for number in phiList]) end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() # so, my first attempt at this used Euler's product formula and was really slow. # Thanks to the people in the forum of P69 of Project Euler for help with this. # we want to maximize n / phi(n). phi(n) = n * product((prime - 1)/prime) for each prime # therefore, we want to maximize 1 / product((prime - 1)/prime) for each prime # let's think about the most naive strategy to get these primes: get the first x primes whose product <= LIMIT # if we were to swap even one of the small primes in this list with a slightly larger prime, then # product((prime - 1)/prime) for each prime would actually get bigger. # thus making 1 / product((prime - 1)/prime) for each prime smaller. # therefore, we just get the first couple primes whose product is <= LIMIT. product = 2 for i in xrange(3, LIMIT + 1, 2): if product * i > LIMIT: break if primeObject.isPrime(i): product *= i end = time() print "Value for which ratio is maximized: ", product print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() # the question is actually asking for the output of the totient function # from 2 to the problem's LIMIT. phiList = [1 for number in xrange(LIMIT + 1)] # defaults. phiList[0] = 0 phiList[1] = 0 for i in xrange(2, LIMIT + 1): if primeObject.isPrime(i): phiList[i] = i - 1 for j in xrange(i * 2, len(phiList), i): phiList[j] *= float(i - 1) / i else: phiList[i] *= i print "Number of reduced, proper fractions where the denominator <= ", LIMIT, " : ", sum( [int(round(number, 0)) for number in phiList]) end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() # so, my first attempt at this used Euler's product formula and was really slow. # Thanks to the people in the forum of P69 of Project Euler for help with this. # we want to maximize n / phi(n). phi(n) = n * product((prime - 1)/prime) for each prime # therefore, we want to maximize 1 / product((prime - 1)/prime) for each prime # let's think about the most naive strategy to get these primes: get the first x primes whose product <= LIMIT # if we were to swap even one of the small primes in this list with a slightly larger prime, then # product((prime - 1)/prime) for each prime would actually get bigger. # thus making 1 / product((prime - 1)/prime) for each prime smaller. # therefore, we just get the first couple primes whose product is <= LIMIT. product = 2 for i in xrange(3, LIMIT + 1, 2): if product * i > LIMIT: break if primeObject.isPrime(i): product *= i end = time() print "Value for which ratio is maximized: ", product print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() solutionSet = set([]) squareList = [ number**2 for number in xrange(2, int(LIMIT**0.5) + 1) if primeObject.isPrime(number) ] cubeList = [ number**3 for number in xrange(2, int(LIMIT**(1. / 3)) + 1) if primeObject.isPrime(number) ] fourthList = [ number**4 for number in xrange(2, int(LIMIT**(1. / 4)) + 1) if primeObject.isPrime(number) ] for square in squareList: for cube in cubeList: if square + cube >= LIMIT: break for fourth in fourthList: resultingSum = square + cube + fourth if resultingSum >= LIMIT: break else: solutionSet.add(resultingSum) print "Number of sums formed from squared, cubed, and fourthed primes that are < ", LIMIT, " : ", len( solutionSet) end = time() print "Runtime: ", end - start, " seconds."
def generate_next_prime(start=2): ''' generator that spits out primes ''' # since 2 is the only even number, # immediately yield it and start # the below loop at the first odd prime. if start == 2: yield 2 start = 3 prime_object = ProjectEulerPrime() while True: if prime_object.isPrime(start): yield start start += 2
def generate_next_prime(start=2): ''' generator that spits out primes ''' # since 2 is the only even number, # immediately yield it and start # the below loop at the first odd prime. if start == 2: yield 2 start = 3 prime_object = ProjectEulerPrime() while True: if prime_object.isPrime(start): yield start start += 2
def main(): start = time() primeObject = ProjectEulerPrime() LIMIT = 10000 # setting a limit too high enables finding 5-way pairs that have huge last numbers (eg, 20000) # 10,000 found through trial and error to be sufficient. primeList = [x for x in xrange(LIMIT) if primeObject.isPrime(x)] solutionList = find5WayPrimes(primeList, primeObject) print "Solutions: ", solutionList print "Sum: ", sum(solutionList) end = time() print "Runtime: ", end - start, " seconds."
def main(): start = time() primeObject = ProjectEulerPrime() LIMIT = 10000 # setting a limit too high enables finding 5-way pairs that have huge last numbers (eg, 20000) # 10,000 found through trial and error to be sufficient. primeList = [x for x in xrange(LIMIT) if primeObject.isPrime(x)] solutionList = find5WayPrimes(primeList, primeObject) print "Solutions: ", solutionList print "Sum: ", sum(solutionList) end = time() print "Runtime: ", end - start, " seconds."
def main(): LIMIT = 4 * 10 ** 6 p = ProjectEulerPrime() # using an algo inspired by hk: # http://projecteuler.net/thread=108 # first step: get a product of unique primes # such that the number of divisors is >= LIMIT. factors = getUniqueFactorization(LIMIT, p) # second step: start minimizing the divisor number with a floor of LIMIT # do this by removing the largest prime and replacing it with # a group of primes s.t. their product is < the largest prime. bestDivisorNumber = getNumberOfDivisors(factors) bestFactorization = factors for largestPrime in reversed(factors): # we need to try to replace each original prime once. iterationBestDivisorNumber = ( bestDivisorNumber ) # these are used so as to not update the absolute minimized factorization iterationBestFactorization = bestFactorization # until we finish a loop. for i in xrange(4, largestPrime): # optimization: skip 2 and 3 as we can't replace primes with another prime. if p.isPrime(i): continue # skip primes. newFactorization = p.factorize(i) newFactorization.extend(bestFactorization) newFactorization.remove(largestPrime) newDivisorNumber = getNumberOfDivisors(newFactorization) if newDivisorNumber >= LIMIT and newDivisorNumber < iterationBestDivisorNumber: iterationBestFactorization = newFactorization iterationBestDivisorNumber = newDivisorNumber bestFactorization = iterationBestFactorization bestDivisorNumber = iterationBestDivisorNumber print "Lowest number with >=", LIMIT, "possible 2 unit fraction additions: ", reduce(mul, bestFactorization) print "Number of additions: ", bestDivisorNumber
def main(): primeObject = ProjectEulerPrime() solution = 0 numberOfWays = [0 for i in xrange(LIMIT + 1)] numberOfWays[0] = 1 # start it off for i in xrange(2, LIMIT + 1): if primeObject.isPrime(i): for j in xrange(i, LIMIT + 1): numberOfWays[j] += numberOfWays[j - i] if numberOfWays[i] >= SUM_LIMIT: solution = i break print "First number to be produced", SUM_LIMIT, "different ways using sums of primes:", solution
def main(): # generate primes. p = ProjectEulerPrime() primes = {2} for i in xrange(3, 100000, 2): if p.isPrime(i): primes.add(i) ''' We use the following facts: R(n) mod(n) => ((10 ** n - 1) / 9) mod n => (10 ** n) mod (9 * n) = 1 x ** y (mod n) == x ** (y mod phi(n)) (mod n) We stop once we detect a repeated residual (which means that we've entered a period). By sheer luck, I used a similar technique in problem 282 to collapse much larger power towers. ''' results = set() for prime in primes: phi_mod = phi(9 * prime) mod = 9 * prime seen_residuals = set() j = 1 while True: residual = pow(10, pow(10, j, phi_mod), mod) if residual in seen_residuals: break if residual == 1: results.add(prime) break seen_residuals.add(residual) j += 1 print "Sum: {}".format(sum(primes - results))
def main(ceiling): primes = ProjectEulerPrime() special_primes = 0 # n ** 3 + p * n ** 2 = x ** 3 can be re-written as: # n ** 2 * (n + p) = x ** 3 # since x, p, and n are positive integers, we know that # n ** 2 and (n + p) must be themselves perfect cubes. # # note that the expression can also be re-written as: # n * (n ** 2 + n * p) = x ** 3, meaning that n must be a perfect cube. # # furthermore, if you inspect the first few primes that # have the special property of the problem, you see this pattern: # p + n = perfect cube (root) # 7 + 1 = 8 (2) # 19 + 8 = 27 (3) # 37 + 27 = 64 (4) # 61 + 64 = 125 (5) # 127 + 216 = 343 (7) # you see that the prime # is that which pushes x ** 3 -> (x + 1) ** 3 # it's also not 100% in effect (n=125, perfect cube = 216) root = 1 while True: difference = (root + 1) ** 3 - root ** 3 # you can see that the gulf between two adjacent perfect cubes # is going to grow larger and larger. eventually, the prime falls out # of our scope. if difference >= ceiling: break elif primes.isPrime(difference): special_primes += 1 root += 1 print "Number of special primes below %d: %d" % (ceiling, special_primes)
def main(): primeObject = ProjectEulerPrime() solution = 0 numberOfWays = [0 for i in xrange(LIMIT + 1)] numberOfWays[0] = 1 # start it off for i in xrange(2, LIMIT + 1): if primeObject.isPrime(i): for j in xrange(i, LIMIT + 1): numberOfWays[j] += numberOfWays[j - i] if numberOfWays[i] >= SUM_LIMIT: solution = i break print "First number to be produced", SUM_LIMIT, "different ways using sums of primes:", solution
def main(): # generate primes. p = ProjectEulerPrime() primes = {2} for i in xrange(3, 100000, 2): if p.isPrime(i): primes.add(i) ''' We use the following facts: R(n) mod(n) => ((10 ** n - 1) / 9) mod n => (10 ** n) mod (9 * n) = 1 x ** y (mod n) == x ** (y mod phi(n)) (mod n) We stop once we detect a repeated residual (which means that we've entered a period). By sheer luck, I used a similar technique in problem 282 to collapse much larger power towers. ''' results = set() for prime in primes: phi_mod = phi(9 * prime) mod = 9 * prime seen_residuals = set() j = 1 while True: residual = pow(10, pow(10, j, phi_mod), mod) if residual in seen_residuals: break if residual == 1: results.add(prime) break seen_residuals.add(residual) j += 1 print "Sum: {}".format(sum(primes - results))
def main(): # the strategy here is to first find # all the primes composed of digits 1-9 # (with at most one of each digit) and to sort # them by size. # We then try all the various ways # of adding up to 9 by adding variously-sized groups # (ie, groups of 1 prime, 2 primes, .... 6 primes) # There can only be at most 6 as primes must end with # an odd number (thus, 5 numbers), and then there's 2. prime_object = ProjectEulerPrime() primes_sorted_by_size = dict() digits = tuple(str(i) for i in xrange(1, 10)) for number_length in xrange(1, len(digits) + 1): for permutation in permutations(digits, number_length): number = int(''.join(permutation)) if prime_object.isPrime(number): if len(permutation) not in primes_sorted_by_size: primes_sorted_by_size[len(permutation)] = set() primes_sorted_by_size[len(permutation)].add(tuple(permutation)) exclusively_prime_groups = 0 # 1-member groups if 9 in primes_sorted_by_size: exclusively_prime_groups += len(primes_sorted_by_size[9]) # 2-member: def two_member_good_group_finder(x, y): if x + y != 9: raise Exception("%d + %d != 9" % (x, y)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) if len(uniques_with_second) == 9: good_groups.add(frozenset([first, second])) return len(good_groups) exclusively_prime_groups += two_member_good_group_finder(8, 1) exclusively_prime_groups += two_member_good_group_finder(7, 2) exclusively_prime_groups += two_member_good_group_finder(6, 3) exclusively_prime_groups += two_member_good_group_finder(5, 4) # 3-member: def three_member_good_group_finder(x, y, z): if x + y + z != 9: raise Exception("%d + %d + %d != 9" % (x, y, z)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue all_uniques = set(uniques_with_second) for digit in third: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add(frozenset([first, second, third])) return len(good_groups) exclusively_prime_groups += three_member_good_group_finder(7, 1, 1) exclusively_prime_groups += three_member_good_group_finder(6, 2, 1) exclusively_prime_groups += three_member_good_group_finder(5, 3, 1) exclusively_prime_groups += three_member_good_group_finder(5, 2, 2) exclusively_prime_groups += three_member_good_group_finder(4, 3, 2) exclusively_prime_groups += three_member_good_group_finder(4, 4, 1) exclusively_prime_groups += three_member_good_group_finder(3, 3, 3) # 4-member: def four_member_good_group_finder(x, y, z, xx): if x + y + z + xx != 9: raise Exception("%d + %d + %d + %d != 9" % (x, y, z, xx)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue all_uniques = set(uniques_with_third) for digit in fourth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add(frozenset([first, second, third, fourth])) return len(good_groups) exclusively_prime_groups += four_member_good_group_finder(6, 1, 1, 1) exclusively_prime_groups += four_member_good_group_finder(5, 2, 1, 1) exclusively_prime_groups += four_member_good_group_finder(4, 2, 2, 1) exclusively_prime_groups += four_member_good_group_finder(4, 3, 1, 1) exclusively_prime_groups += four_member_good_group_finder(3, 3, 2, 1) exclusively_prime_groups += four_member_good_group_finder(3, 2, 2, 2) # 5-member: def five_member_good_group_finder(x, y, z, xx, yy): if x + y + z + xx + yy != 9: raise Exception("%d + %d + %d + %d + %d != 9" % (x, y, z, xx, yy)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue uniques_with_fourth = set(uniques_with_third) for digit in fourth: uniques_with_fourth.add(digit) for fifth in primes_sorted_by_size[yy]: if fifth == first or fifth == second or \ fifth == third or fifth == fourth: continue all_uniques = set(uniques_with_fourth) for digit in fifth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add(frozenset([first, second, third, fourth, fifth])) return len(good_groups) exclusively_prime_groups += five_member_good_group_finder(5, 1, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(4, 2, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(3, 3, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(3, 2, 2, 1, 1) exclusively_prime_groups += five_member_good_group_finder(2, 2, 2, 2, 1) # 6-member def six_member_good_group_finder(x, y, z, xx, yy, zz): if x + y + z + xx + yy + zz != 9: raise Exception("%d + %d + %d + %d + %d != 9" % (x, y, z, xx, yy, zz)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue uniques_with_fourth = set(uniques_with_third) for digit in fourth: uniques_with_fourth.add(digit) for fifth in primes_sorted_by_size[yy]: if fifth == first or fifth == second or \ fifth == third or fifth == fourth: continue uniques_with_fifth = set(uniques_with_fourth) for digit in fifth: uniques_with_fifth.add(digit) for sixth in primes_sorted_by_size[zz]: if sixth == first or sixth == second or \ sixth == third or sixth == fourth or \ sixth == fifth: continue all_uniques = set(uniques_with_fifth) for digit in sixth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add(frozenset([first, second, third, fourth, fifth, sixth])) return len(good_groups) exclusively_prime_groups += six_member_good_group_finder(2, 2, 2, 1, 1, 1) exclusively_prime_groups += six_member_good_group_finder(2, 3, 1, 1, 1, 1) print "Number of groups: %d" % exclusively_prime_groups
def main(): # the strategy here is to first find # all the primes composed of digits 1-9 # (with at most one of each digit) and to sort # them by size. # We then try all the various ways # of adding up to 9 by adding variously-sized groups # (ie, groups of 1 prime, 2 primes, .... 6 primes) # There can only be at most 6 as primes must end with # an odd number (thus, 5 numbers), and then there's 2. prime_object = ProjectEulerPrime() primes_sorted_by_size = dict() digits = tuple(str(i) for i in xrange(1, 10)) for number_length in xrange(1, len(digits) + 1): for permutation in permutations(digits, number_length): number = int(''.join(permutation)) if prime_object.isPrime(number): if len(permutation) not in primes_sorted_by_size: primes_sorted_by_size[len(permutation)] = set() primes_sorted_by_size[len(permutation)].add(tuple(permutation)) exclusively_prime_groups = 0 # 1-member groups if 9 in primes_sorted_by_size: exclusively_prime_groups += len(primes_sorted_by_size[9]) # 2-member: def two_member_good_group_finder(x, y): if x + y != 9: raise Exception("%d + %d != 9" % (x, y)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) if len(uniques_with_second) == 9: good_groups.add(frozenset([first, second])) return len(good_groups) exclusively_prime_groups += two_member_good_group_finder(8, 1) exclusively_prime_groups += two_member_good_group_finder(7, 2) exclusively_prime_groups += two_member_good_group_finder(6, 3) exclusively_prime_groups += two_member_good_group_finder(5, 4) # 3-member: def three_member_good_group_finder(x, y, z): if x + y + z != 9: raise Exception("%d + %d + %d != 9" % (x, y, z)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue all_uniques = set(uniques_with_second) for digit in third: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add(frozenset([first, second, third])) return len(good_groups) exclusively_prime_groups += three_member_good_group_finder(7, 1, 1) exclusively_prime_groups += three_member_good_group_finder(6, 2, 1) exclusively_prime_groups += three_member_good_group_finder(5, 3, 1) exclusively_prime_groups += three_member_good_group_finder(5, 2, 2) exclusively_prime_groups += three_member_good_group_finder(4, 3, 2) exclusively_prime_groups += three_member_good_group_finder(4, 4, 1) exclusively_prime_groups += three_member_good_group_finder(3, 3, 3) # 4-member: def four_member_good_group_finder(x, y, z, xx): if x + y + z + xx != 9: raise Exception("%d + %d + %d + %d != 9" % (x, y, z, xx)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue all_uniques = set(uniques_with_third) for digit in fourth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add( frozenset([first, second, third, fourth])) return len(good_groups) exclusively_prime_groups += four_member_good_group_finder(6, 1, 1, 1) exclusively_prime_groups += four_member_good_group_finder(5, 2, 1, 1) exclusively_prime_groups += four_member_good_group_finder(4, 2, 2, 1) exclusively_prime_groups += four_member_good_group_finder(4, 3, 1, 1) exclusively_prime_groups += four_member_good_group_finder(3, 3, 2, 1) exclusively_prime_groups += four_member_good_group_finder(3, 2, 2, 2) # 5-member: def five_member_good_group_finder(x, y, z, xx, yy): if x + y + z + xx + yy != 9: raise Exception("%d + %d + %d + %d + %d != 9" % (x, y, z, xx, yy)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue uniques_with_fourth = set(uniques_with_third) for digit in fourth: uniques_with_fourth.add(digit) for fifth in primes_sorted_by_size[yy]: if fifth == first or fifth == second or \ fifth == third or fifth == fourth: continue all_uniques = set(uniques_with_fourth) for digit in fifth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add( frozenset( [first, second, third, fourth, fifth])) return len(good_groups) exclusively_prime_groups += five_member_good_group_finder(5, 1, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(4, 2, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(3, 3, 1, 1, 1) exclusively_prime_groups += five_member_good_group_finder(3, 2, 2, 1, 1) exclusively_prime_groups += five_member_good_group_finder(2, 2, 2, 2, 1) # 6-member def six_member_good_group_finder(x, y, z, xx, yy, zz): if x + y + z + xx + yy + zz != 9: raise Exception("%d + %d + %d + %d + %d != 9" % (x, y, z, xx, yy, zz)) good_groups = set() for first in primes_sorted_by_size[x]: uniques = set(digit for digit in first) for second in primes_sorted_by_size[y]: if first == second: continue uniques_with_second = set(uniques) for digit in second: uniques_with_second.add(digit) for third in primes_sorted_by_size[z]: if third == second or third == first: continue uniques_with_third = set(uniques_with_second) for digit in third: uniques_with_third.add(digit) for fourth in primes_sorted_by_size[xx]: if fourth == third or fourth == second or \ fourth == first: continue uniques_with_fourth = set(uniques_with_third) for digit in fourth: uniques_with_fourth.add(digit) for fifth in primes_sorted_by_size[yy]: if fifth == first or fifth == second or \ fifth == third or fifth == fourth: continue uniques_with_fifth = set(uniques_with_fourth) for digit in fifth: uniques_with_fifth.add(digit) for sixth in primes_sorted_by_size[zz]: if sixth == first or sixth == second or \ sixth == third or sixth == fourth or \ sixth == fifth: continue all_uniques = set(uniques_with_fifth) for digit in sixth: all_uniques.add(digit) if len(all_uniques) == 9: good_groups.add( frozenset([ first, second, third, fourth, fifth, sixth ])) return len(good_groups) exclusively_prime_groups += six_member_good_group_finder(2, 2, 2, 1, 1, 1) exclusively_prime_groups += six_member_good_group_finder(2, 3, 1, 1, 1, 1) print "Number of groups: %d" % exclusively_prime_groups