Ejemplo n.º 1
0
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."
Ejemplo n.º 2
0
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."
Ejemplo n.º 3
0
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."
Ejemplo n.º 4
0
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."
Ejemplo n.º 5
0
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."
Ejemplo n.º 6
0
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))
Ejemplo n.º 7
0
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."
Ejemplo n.º 8
0
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."
Ejemplo n.º 9
0
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."
Ejemplo n.º 10
0
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."
Ejemplo n.º 11
0
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
Ejemplo n.º 13
0
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
Ejemplo n.º 14
0
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."
Ejemplo n.º 15
0
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."                                        
Ejemplo n.º 16
0
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
Ejemplo n.º 17
0
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 
Ejemplo n.º 18
0
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))
Ejemplo n.º 19
0
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)
Ejemplo n.º 20
0
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
Ejemplo n.º 21
0
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))
Ejemplo n.º 22
0
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
Ejemplo n.º 23
0
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