Esempio n. 1
0
def problem087():
    """


    The smallest number expressible as the sum of a prime square, prime cube,
       and prime fourth power is 28. In fact, there are exactly four numbers
       below fifty that can be expressed in such a way:

       28 = 2^2 + 2^3 + 2^4
       33 = 3^2 + 2^3 + 2^4
       49 = 5^2 + 2^3 + 2^4
       47 = 2^2 + 3^3 + 2^4

       How many numbers below fifty million can be expressed as the sum of a
       prime square, prime cube, and prime fourth power?
    """
    limit = 50000000
    primes = eulerlib.list_primes(eulerlib.sqrt(limit))

    sums = {0}
    for i in range(2, 5):
        newsums = set()
        for p in primes:
            q = p**i
            if q > limit:
                break
            for x in sums:
                if x + q <= limit:
                    newsums.add(x + q)
        sums = newsums
    return len(sums)
Esempio n. 2
0
def problem111():
    DIGITS = 10

    primes = eulerlib.list_primes(eulerlib.sqrt(10**DIGITS))

    # Only valid if 1 < n <= 10^DIGITS.
    def is_prime(n):
        end = eulerlib.sqrt(n)
        for p in primes:
            if p > end:
                break
            if n % p == 0:
                return False
        return True

    ans = 0
    # For each repeating digit
    for digit in range(10):

        # Search by the number of repetitions in decreasing order
        for rep in range(DIGITS, -1, -1):
            sum = 0
            digits = [0] * DIGITS

            # Try all possibilities for filling the non-repeating digits
            for i in range(9**(DIGITS - rep)):

                # Build initial array. For example, if DIGITS=7, digit=5, rep=4, i=123, then the array will be filled with 5,5,5,5,1,4,7.
                for j in range(rep):
                    digits[j] = digit
                temp = i
                for j in range(DIGITS - rep):
                    d = temp % 9
                    if d >= digit:  # Skip the repeating digit
                        d += 1
                    if (
                            j > 0 and d > digits[DIGITS - j]
                    ):  # If this is true, then after sorting, the array will be in an already-tried configuration
                        break
                    digits[-1 - j] = d
                    temp //= 9

                else:
                    digits.sort()  # Start at lowest permutation

                    while True:  # Go through all permutations
                        if (
                                digits[0] > 0
                        ):  # Skip if the number has a leading zero, which means it has less than DIGIT digits
                            num = int("".join(map(str, digits)))
                            if is_prime(num):
                                sum += num
                        if not eulerlib.next_permutation(digits):
                            break

            if sum > 0:  # Primes found; skip all lesser repetitions
                ans += sum
                break

    return ans
Esempio n. 3
0
def problem050():
    """


    The prime 41, can be written as the summation of six consecutive primes:

                              41 = 2 + 3 + 5 + 7 + 11 + 13

       This is the longest summation of consecutive primes that adds to a prime below
       one-hundred.

       The longest summation of consecutive primes below one-thousand that adds to a
       prime, contains 21 terms, and is equal to 953.

       Which prime, below one-million, can be written as the summation of the most
       consecutive primes?
    """
    ans = 0
    isprime = eulerlib.list_primality(999999)
    primes = eulerlib.list_primes(999999)
    consecutive = 0
    for i in range(len(primes)):
        summation = primes[i]
        consec = 1
        for j in range(i + 1, len(primes)):
            summation += primes[j]
            consec += 1
            if summation >= len(isprime):
                break
            if isprime[summation] and consec > consecutive:
                ans = summation
                consecutive = consec
    return ans
Esempio n. 4
0
def problem304():
    BASE = 10 ** 14
    SEARCH_RANGE = (
        10000000
    )  # Number of candidates starting from BASE to search for primes. Hopefully there are 100 000 primes among here.
    MODULUS = 1234567891011

    # iscomposite[i] pertains to the number BASE + i
    # Sieve of Eratosthenes, but starting at BASE
    iscomposite = [False] * SEARCH_RANGE
    primes = eulerlib.list_primes(eulerlib.sqrt(BASE + SEARCH_RANGE))
    for p in primes:
        for i in range((BASE + p - 1) // p * p - BASE, len(iscomposite), p):
            iscomposite[i] = True

    # Returns p - BASE, where p is the next prime after n + BASE
    def next_prime(n):
        while True:
            n += 1
            if n >= len(iscomposite):
                raise AssertionError("Search range exhausted")
            if not iscomposite[n]:
                return n

    ans = 0
    p = 0
    for i in range(100000):
        p = next_prime(p)
        ans = (ans + fibonacci_mod(BASE + p, MODULUS)) % MODULUS
    return ans
Esempio n. 5
0
def problem134():
    """
    Let p and q be the two primes. Let k be the smallest power of 10 that exceeds p.
    The number that we seek is n = mk + p, where n is divisible by q, and m is minimized.
    (For example, p = 19, q = 23, k = 100, m = 12, n = 1219.)


    Firstly, n = mk + p = 0 mod q. By rearrangement, m = -p k^-1 mod q. (k^-1 exists because q is coprime with 10.)
    Then of course the smallest m that satisfies the divisibility condition is the one such that 0 <= m < q.

    :return:
    """
    ans = 0
    primes = eulerlib.list_primes(2000000)
    for i in itertools.count(2):
        p = primes[i]
        q = primes[i + 1]
        if p > 1000000:
            break
        k = 1
        while k < p:
            k *= 10
        m = (q - p) * eulerlib.reciprocal_mod(k % q, q) % q
        ans += m * k + p
    return ans
Esempio n. 6
0
def problem146():
    LIMIT = 150000000

    INCREMENTS = [1, 3, 7, 9, 13, 27]  # Must be in non-decreasing order
    NON_INCREMENTS = set(range(INCREMENTS[-1])) - set(INCREMENTS)

    maxnumber = LIMIT ** 2 + INCREMENTS[-1]
    primes = eulerlib.list_primes(eulerlib.sqrt(maxnumber))

    def has_consecutive_primes(n):
        # Generate the set of numbers to test for primality
        n2 = n ** 2
        temp = [(n2 + k) for k in INCREMENTS]

        # Test that each number is prime.
        # Note: The nesting of the loops can be reversed, but this way is much faster.
        if any((x != p and x % p == 0) for p in primes for x in temp):
            return False

        # Test that each number that is not an increment is composite.
        # This checks that the prime numbers we found are in fact consecutive.
        return all((not is_prime(n2 + k)) for k in NON_INCREMENTS)

    def is_prime(n):
        end = eulerlib.sqrt(n)
        for p in primes:
            if p > end:
                break
            if n % p == 0:
                return False
        return True

    ans = sum(n for n in range(0, LIMIT, 10) if has_consecutive_primes(n))
    return ans
Esempio n. 7
0
def problem010():
    """
    The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.
    Find the sum of all the primes below two million.

    Call the sieve of Eratosthenes and sum the primes found.
    """

    ans = sum(eulerlib.list_primes(1999999))
    return ans
Esempio n. 8
0
def problem187():
    LIMIT = 10**8 - 1
    ans = 0
    primes = eulerlib.list_primes(LIMIT // 2)
    sqrt = eulerlib.sqrt(LIMIT)
    for (i, p) in enumerate(primes):
        if p > sqrt:
            break
        end = binary_search(primes, LIMIT // p)
        ans += (end + 1 if end >= 0 else -end - 1) - i
    return ans
Esempio n. 9
0
def problem204():
    LIMIT = 10**9
    primes = eulerlib.list_primes(100)

    def count(primeindex, product):
        if primeindex == len(primes):
            return 1 if product <= LIMIT else 0
        else:
            result = 0
            while product <= LIMIT:
                result += count(primeindex + 1, product)
                product *= primes[primeindex]
            return result

    return count(0, 1)
Esempio n. 10
0
def problem347():
    """


    The largest integer ≤ 100 that is only divisible by both the primes 2 and
       3 is 96, as 96=32*3=2^5*3.For two distinct primes p and q let M(p,q,N) be
       the largest positive integer ≤N only divisibleby both p and q and
       M(p,q,N)=0 if such a positive integer does not exist.

       E.g. M(2,3,100)=96.
       M(3,5,100)=75 and not 90 because 90 is divisible by 2 ,3 and 5.
       Also M(2,73,100)=0 because there does not exist a positive integer ≤ 100
       that is divisible by both 2 and 73.

       Let S(N) be the sum of all distinct M(p,q,N).S(100)=2262.

       Find S(10 000 000).
    """
    limit = 10000000

    possible = set()
    primes = eulerlib.list_primes(limit // 2)
    end = eulerlib.sqrt(limit)
    for i in range(len(primes)):
        p = primes[i]
        if p > end:
            break
        for j in range(i + 1, len(primes)):
            q = primes[j]
            lcm = p * q
            if lcm > limit:
                break
            multlimit = limit // lcm

            multiplier = 1
            while multiplier * p <= multlimit:
                multiplier *= p
            maxmult = multiplier
            while multiplier % p == 0:
                multiplier //= p
                while multiplier * q <= multlimit:
                    multiplier *= q
                maxmult = max(multiplier, maxmult)
            possible.add(maxmult * lcm)

    ans = sum(possible)
    return ans
Esempio n. 11
0
def problem249():
    LIMIT = 5000
    MODULUS = 10**16

    # Use dynamic programming. count[i] is the number of subsets of primes with the sum of i, modulo MODULUS.
    count = [0] * (LIMIT**2 // 2)
    count[0] = 1
    s = (
        0
    )  # Sum of all primes seen so far, and thus the highest index among nonzero entries in 'count'
    for p in eulerlib.list_primes(LIMIT):
        for i in reversed(range(s + 1)):
            count[i + p] = (count[i + p] + count[i]) % MODULUS
        s += p

    isprime = eulerlib.list_primality(s + 1)
    ans = sum(count[i] for i in range(s + 1) if isprime[i]) % MODULUS
    return ans
Esempio n. 12
0
def problem203():
    # Collect unique numbers in Pascal's triangle
    numbers = set(eulerlib.binomial(n, k) for n in range(51) for k in range(n + 1))
    maximum = max(numbers)

    # Prepare list of squared primes
    primes = eulerlib.list_primes(eulerlib.sqrt(maximum))
    primessquared = [p * p for p in primes]

    def is_squarefree(n):
        for p2 in primessquared:
            if p2 > n:
                break
            if n % p2 == 0:
                return False
        return True

    # Sum up the squarefree numbers
    ans = sum(n for n in numbers if is_squarefree(n))
    return ans
Esempio n. 13
0
def problem133():
    primes = eulerlib.list_primes(100000)
    ans = sum(p for p in primes
              if p == 2 or p == 5 or not has_divisible_repunit(p))
    return ans
Esempio n. 14
0
def problem123():
    primes = eulerlib.list_primes(1000000)
    for n in range(5, len(primes), 2):
        rem = n * primes[n - 1] * 2
        if rem > 10000000000:
            return n
Esempio n. 15
0
def test_list_primes(input_n, expected_output):
    output = eulerlib.list_primes(input_n)
    print(output)
    assert output == expected_output
Esempio n. 16
0
def problem060():
    """
    The primes 3, 7, 109, and 673, are quite remarkable. By taking any two
    primes and concatenating them in any order the result will always be
    prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The
    sum of these four primes, 792, represents the lowest sum for a set of four
    primes with this property.
    Find the lowest sum for a set of five primes for which any two primes
    concatenate to produce another prime.
    """

    prime_limit = 100000  # Arbitrary initial cutoff
    primes = eulerlib.list_primes(prime_limit)

    # Tries to find any suitable set and return its sum, or None if none is found.
    # A set is suitable if it contains only primes, its size is targetsize,
    # its sum is less than or equal to sumlimit, and each pair concatenates to a prime.
    # 'prefix' is an array of ascending indices into the 'primes' array,
    # which describes the set found so far.
    # The function blindly assumes that each pair of primes in 'prefix' concatenates to a prime.
    # For example, find_set_sum([1, 3, 28], 5, 10000) means "find the sum of any set
    # where the set has size 5, consists of primes with the lowest elements being [3, 7, 109],
    # has sum 10000 or less, and has each pair concatenating to form a prime".
    def find_set_sum(prefix, targetsize, sum_limitation):
        if len(prefix) == targetsize:
            return sum(primes[i] for i in prefix)
        else:
            istart = 0 if (len(prefix) == 0) else (prefix[-1] + 1)
            for i in range(istart, len(primes)):
                if primes[i] > sum_limitation:
                    break
                if all((is_concat_prime(i, j) and is_concat_prime(j, i))
                       for j in prefix):
                    prefix.append(i)
                    result = find_set_sum(prefix, targetsize,
                                          sum_limitation - primes[i])
                    prefix.pop()
                    if result is not None:
                        return result
            return None

    # Tests whether concat(primes[x], primes[y]) is a prime number, with memoization.
    @eulerlib.Memoize
    def is_concat_prime(x, y):
        return is_prime(int(str(primes[x]) + str(primes[y])))

    # Tests whether the given integer is prime. The implementation performs trial division,
    # first using the list of primes named 'primes', then switching to simple incrementation.
    # This requires the last number in 'primes' (if any) to be an odd number.
    def is_prime(x):
        if x < 0:
            raise ValueError()
        elif x in (0, 1):
            return False
        else:
            end = eulerlib.sqrt(x)
            for p in primes:
                if p > end:
                    break
                if x % p == 0:
                    return False
            for i in range(primes[-1] + 2, end + 1, 2):
                if x % i == 0:
                    return False
            return True

    sumlimit = prime_limit
    while True:
        setsum = find_set_sum([], 5, sumlimit - 1)
        if setsum is None:  # No smaller sum found
            return sumlimit
        sumlimit = setsum