예제 #1
0
def run():
    limit = 10_000  # We're interested in 4-digit primes, i.e. primes < 10000.
    sieve = prime_sieve(limit)

    # Loop through all 4-digit primes:
    for primeCandidate in range(1000, limit - 1):
        if sieve[primeCandidate]:
            continue

        # We're looking for three evenly spaced prime numbers below 10000.
        # So we can at most add ((limit - 1) - primeCandidate) / 2, twice.
        upperLimit = int(((limit - 1) - primeCandidate) / 2)
        for j in range(1, upperLimit):
            # Calculate the two candidates, then check whether they're prime:
            primeCandidate2 = primeCandidate + j
            primeCandidate3 = primeCandidate + (2 * j)
            if sieve[primeCandidate2] or sieve[primeCandidate3]:
                continue

            # Now we know all three numbers are prime, we still have to test
            # whether they're also permutations of one another:
            else:
                sortedPrime = sorted(str(primeCandidate))
                if sortedPrime == sorted(
                        str(primeCandidate2)) and sortedPrime == sorted(
                            str(primeCandidate3)):
                    # Now we concatenate the three primes into the answer string,
                    # and make sure that it's not the answer already provided in the problem description.
                    answer_string = str(primeCandidate) + str(
                        primeCandidate2) + str(primeCandidate3)
                    if answer_string != "148748178147":
                        return answer_string
예제 #2
0
def run():
    # Generate the prime sieve, and create a generator for all primes below the limit.
    limit = 1_000_000  # arbitrary, but it yields the correct result
    sieve = prime_sieve(limit)
    primes = (i for i in range(1, limit) if not sieve[i])

    for prime in primes:
        prime_length = len(str(prime))
        # Loop through all possibilities of how many digits to replace - at most all but one.
        # Then use itertools.combinations to yield all combinations of which *digit positions* to replace.
        # The construction below yields all the combinations of the integers 0 ... len(prime)
        # of length amount_to_replace, in sorted order, i.e. there could be a "0129",
        # but then there'd be no "9012". Which is exactly what I want.
        for amount_to_replace in range(1, prime_length):
            for digitsToReplace in combinations(range(prime_length),
                                                amount_to_replace):
                primeFamily = []
                newNumberList = [digit for digit in str(prime)]
                for newDigit in range(
                        10
                ):  # Replace the chosen digits with the numbers 0...9.
                    for index in digitsToReplace:
                        newNumberList[index] = str(newDigit)
                    newNumber = int("".join(newNumberList))
                    # If newNumber begins with a zero, disregard it:
                    if len(str(newNumber)) < prime_length:
                        continue
                    # If newNumber is prime, add it to the primeFamily.
                    if not sieve[newNumber]:
                        primeFamily.append(newNumber)
                # If we've found a primeFamily of length 8, we're done:
                if len(primeFamily) == 8:
                    return min(primeFamily)
예제 #3
0
def run():
    limit = 800_000  # arbitrary, but it yields the correct result
    sieve = prime_sieve(limit)

    count_trunc = 0
    truncSum = 0

    for primeCandidate in range(
            11, limit -
            1):  # The single-digit primes aren't considered truncatable.
        if not sieve[primeCandidate]:  # sieve[4] is True if 4 is *not* prime.
            truncLeft = str(primeCandidate)
            truncRight = str(primeCandidate)
            while True:
                # Truncate the primes. Then if the truncated numbers
                # aren't prime anymore, exit the loop.
                truncLeft = truncLeft[1:]
                truncRight = truncRight[:-1]
                if sieve[int(truncLeft)] or sieve[int(truncRight)]:
                    break

                # Otherwise, check whether the numbers have been truncated to 1 digit,
                # in which case we've found a new truncatable prime.
                if len(truncLeft) == 1:
                    count_trunc += 1
                    truncSum += primeCandidate
                    break
        # According to the description, there are only 11 truncatable primes.
        # So we're done once we've found them all.
        if count_trunc >= 11:
            return truncSum
예제 #4
0
def run():
    limit = 150_000  # According to https://primes.utm.edu/howmany.html, there are ~10000 primes below ~100000.
    sieve = prime_sieve(limit)

    counter = 0
    for n in range(limit):
        if not sieve[n]:  # False = prime
            counter += 1
            if counter == 10001:
                return n
예제 #5
0
def run():
    # Generate the prime sieve, and create a list of all primes below the limit.
    limit = 1_000_000  # Primes below one million.
    sieve = prime_sieve(limit)
    primeList = [i for i in range(1, limit) if not sieve[i]]

    # Initialize some variables:
    lowerLimit = 0
    max_summands = 0
    prime_with_most_summands = 0

    # Loop through all primes in descending order.
    primeIndex = len(primeList) - 1  # Begin with the largest prime in the list. If a list has 5 elements, it has length 5, but its largest index is 4.
    prime = primeList[primeIndex]
    while prime > lowerLimit:
        prime_sum = 0
        summandList = deque()
        # Loop through all primes <= prime, then sum up consecutive primes
        # and check whether the sum equals prime.
        # Because we begin the sum with the smallest prime, once prime_sum == prime,
        # we've automatically found the sum with the most summands for this prime.
        for summandIndex in range(primeIndex):
            if prime_sum < prime:
                summand = primeList[summandIndex]
                prime_sum += summand
                summandList.append(summand)
            elif prime_sum == prime:
                # We've constructed the given prime as a sum of consecutive primes.
                # Now we count the number of summands sumCounter and test if it's a new maximum.
                # If it is, we increase the lower limit accordingly, so that it always corresponds to
                # the sum of the sumCounter lowest primes.
                sumCounter = len(summandList)
                if sumCounter > max_summands:
                    # Increase the lower limit by however many summands have been added due to the increase in max:
                    for i in range(max_summands, sumCounter):
                        lowerLimit += primeList[i]
                    max_summands = sumCounter
                    prime_with_most_summands = prime
            # Otherwise, prime_sum > prime, and we have to subtract summands from the left 
            # until prime_sum <= prime again.
            else:
                while prime_sum > prime:
                    prime_sum -= summandList.popleft()
        # Finally, we go to the next-largest prime.
        primeIndex -= 1
        prime = primeList[primeIndex]

    return prime_with_most_summands
예제 #6
0
def run():
    limit = 1_000_000  # primes below 1000000
    sieve = prime_sieve(limit)

    # Loop through all primes. Rotate the primes,
    # then check if their rotations are also prime.
    count_circular = 0
    for primeCandidate in range(1, limit - 1):
        if not sieve[primeCandidate]:  # sieve[4] is True if 4 is *not* prime.
            candidateList = rotateNumber(primeCandidate)
            # If all the rotated candidates are prime, we've found a circular prime.
            for rotated_number in candidateList:
                if sieve[rotated_number]:
                    break
            else:  # Triggers if the for-loop wasn't stopped early.
                count_circular += 1
    return count_circular
예제 #7
0
def run():
    limit = 1_000_000  # Check primes below 1000000
    sieve = prime_sieve(limit)

    # Loop through the composite numbers:
    for compositeCandidate in range(4, limit - 1):
        # Check whether the current number and the next three consecutive numbers in the sieve
        # are all composite. If they aren't, skip to the next compositeCandidate.
        for i in range(3 + 1):
            if not sieve[compositeCandidate + i]:
                break
        # Now that we've found four consecutive composite numbers,
        # we count their distinct prime factors.
        else:
            for j in range(3 + 1):
                if count_unique_prime_factors(compositeCandidate + j,
                                              sieve) < 4:
                    break
            # Once we've found four consecutive composites with
            # at least 4 distinct prime factors each, we're done.
            else:
                return compositeCandidate
예제 #8
0
def run():
    limit = 1_000_000  # arbitrary, but it yields the correct result
    sieve = prime_sieve(limit)

    # Loop through all odd composites, so begin with 9 (all smaller odd numbers are prime),
    # and use a step size of 2.
    for compositeCandidate in range(9, limit - 1, 2):
        if sieve[
                compositeCandidate]:  # sieve[4] is True if 4 is composite, i.e. not prime.
            # Once we've found an odd composite, we try to test the conjecure,
            # i.e. we try to write the composite as the sum of a prime and twice a square.

            # First, we loop through all valid squares for the "twice a square" part of the conjecture.
            # The upper limit comes from setting the prime to 0, so composite = 0 + 2*a**2
            # -> a = sqrt(composite/2) is the upper limit for a.
            for i in range(1, int(sqrt(compositeCandidate / 2)) + 1):
                doubleSquare = 2 * (i**2)
                # Finally, we test if the composite minus the doubled square is still prime:
                # composite = potentialPrime + doubleSquare -> potentialPrime = composite - doubleSquare.
                if not sieve[compositeCandidate - doubleSquare]:
                    break
            # We're done once we've found an odd composite which doesn't fulfill the condition:
            else:
                return compositeCandidate
예제 #9
0
def run():
    limit = 2_000_000  # Numbers *below* 2,000,000.
    sieve = prime_sieve(limit)
    prime_sum = sum(n for n in range(limit) if not sieve[n])
    return prime_sum