def problem518(): LIMIT = 10 ** 8 ans = 0 isprime = eulerlib.list_primality(LIMIT - 1) # Search all possible x's. We know that c = x * z * z - 1. With the requirement c < LIMIT, we have x * z * z <= LIMIT. # Because z > y > 0, we know z >= 2. So at the very least we require x * 4 <= LIMIT. This implies x <= floor(LIMIT/4). for x in range(1, LIMIT // 4 + 1): # Search all possible y's. Notice that when y increases, 'a' strictly increases. # So when some y generates an 'a' such that a >= LIMIT, no candidates are possible with higher values of y. for y in itertools.count(1): a = x * y * y - 1 if a >= LIMIT: break if not isprime[a]: continue # Search all valid z's. We require z > y and gcd(y, z) = 1. Notice that when z increases, c strictly increases. # So when some z generates a c such that c >= LIMIT, no candidates are possible with higher values of z. for z in itertools.count(y + 1): if math.gcd(y, z) != 1: continue c = x * z * z - 1 if c >= LIMIT: break # Check whether (a, b, c) is a solution if isprime[c]: b = x * y * z - 1 if isprime[b]: ans += a + b + c return ans
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
def problem118(): isprime = eulerlib.list_primality(10000) # Cache for small numbers digits = list(range(1, 10)) def count_prime_sets(startindex, prevnum): if startindex == len(digits): return 1 else: result = 0 for split in range(startindex + 1, len(digits) + 1): num = int("".join(map(str, digits[startindex:split]))) if num > prevnum and is_prime(num): result += count_prime_sets(split, num) return result def is_prime(n): if n < len(isprime): return isprime[n] else: return eulerlib.is_prime(n) ans = 0 while True: ans += count_prime_sets(0, 0) if not eulerlib.next_permutation(digits): break return ans
def problem329(): START_NUM = 1 END_NUM = 500 CROAK_SEQ = "PPPPNNPPPNPPNPN" assert 0 <= START_NUM < END_NUM assert 1 <= len(CROAK_SEQ) NUM_JUMPS = len(CROAK_SEQ) - 1 NUM_TRIALS = 2**NUM_JUMPS globalnumerator = 0 isprime = eulerlib.list_primality(END_NUM) # For each starting square for i in range(START_NUM, END_NUM + 1): # For each sequence of jumps for j in range(NUM_TRIALS): # Set initial position and croak pos = i trialnumerator = 1 if isprime[pos] == (CROAK_SEQ[0] == "P"): trialnumerator *= 2 # Simulate each jump and croak for k in range(NUM_JUMPS): if pos <= START_NUM: pos += 1 # Forced move elif pos >= END_NUM: pos -= 1 # Forced move elif (j >> k) & 1 == 0: pos += 1 # Chosen move else: pos -= 1 # Chosen move # Multiply the running probability by 2/3 if primeness of current position # matches croak sequence at current index, otherwise multiply by 1/3 if isprime[pos] == (CROAK_SEQ[k + 1] == "P"): trialnumerator *= 2 globalnumerator += trialnumerator # Calculate final probability fraction globaldenominator = (END_NUM + 1 - START_NUM) * 2**NUM_JUMPS * 3**len(CROAK_SEQ) ans = fractions.Fraction(globalnumerator, globaldenominator) return ans
def problem425(): LIMIT = 10 ** 7 isprime = eulerlib.list_primality(LIMIT) # pathmax[i] = None if i is not prime or i is not connected to 2. # Otherwise, considering all connection paths from 2 to i and for each path computing # the maximum number, pathmax[i] is the minimum number among all these maxima. pathmax = [None] * len(isprime) # Process paths in increasing order of maximum number queue = [(2, 2)] while len(queue) > 0: pmax, n = heapq.heappop(queue) if pathmax[n] is not None and pmax >= pathmax[n]: # This happens if at the time this update was queued, a better # or equally good update was queued ahead but not processed yet continue # Update the target node and explore neighbors pathmax[n] = pmax # Try all replacements of a single digit, including the leading zero. # This generates exactly all (no more, no less) the ways that a number m is connected to n. digits = to_digits(n) tempdigits = list(digits) for i in range(len(tempdigits)): # For each digit position for j in range(10): # For each digit value tempdigits[i] = j m = to_number(tempdigits) nextpmax = max(m, pmax) if ( m < len(isprime) and isprime[m] and (pathmax[m] is None or nextpmax < pathmax[m]) ): heapq.heappush(queue, (nextpmax, m)) tempdigits[i] = digits[i] # Restore the digit ans = sum( i for i in range(len(isprime)) if isprime[i] and (pathmax[i] is None or pathmax[i] > i) ) return ans
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
def count_circular_primes(upper_bound=999999): """ The number, 197, is called a circular prime because all rotations of the digits: 197, 971, and 719, are themselves prime. There are thirteen such primes below 100: 2, 3, 5, 7, 11, 13, 17, 31, 37, 71, 73, 79, and 97. How many circular primes are there below one million? """ is_prime = eulerlib.list_primality(upper_bound) def is_circular_prime(input_n): n_string = str(input_n) return all( is_prime[int(n_string[i:] + n_string[:i])] for i in range(len(n_string)) ) ans = sum(1 for i in range(len(is_prime)) if is_circular_prime(i)) return ans
def problem357(): """ Consider the divisors of 30: 1,2,3,5,6,10,15,30. It can be seen that for every divisor d of 30, d+30/d is prime. Find the sum of all positive integers n not exceeding 100 000 000 such thatfor every divisor d of n, d+n/d is prime. """ limit = 10**8 isprime = eulerlib.list_primality(limit + 1) def is_prime_generating(n): return all((n % d != 0 or isprime[d + n // d]) for d in range(2, eulerlib.sqrt(n) + 1)) ans = sum(n for n in range(limit + 1) if isprime[n + 1] and is_prime_generating(n)) return ans
def problem051(): """ By replacing the 1^st digit of the 2-digit number *3, it turns out that six of the nine possible values: 13, 23, 43, 53, 73, and 83, are all prime. By replacing the 3^rd and 4^th digits of 56**3 with the same digit, this 5-digit number is the first example having seven primes among the ten generated numbers, yielding the family: 56003, 56113, 56333, 56443, 56663, 56773, and 56993. Consequently 56003, being the first member of this family, is the smallest prime with this property. Find the smallest prime which, by replacing part of the number (not necessarily adjacent digits) with the same digit, is part of an eight prime value family. """ isprime = eulerlib.list_primality(1000000) for i in range(len(isprime)): if not isprime[i]: continue n = [int(c) for c in str(i)] for mask in range(1 << len(n)): digits = do_mask(n, mask) count = 0 for j in range(10): if digits[0] != 0 and isprime[to_number(digits)]: count += 1 digits = add_mask(digits, mask) if count == 8: digits = do_mask(n, mask) for j in range(10): if digits[0] != 0 and isprime[to_number(digits)]: return to_number(digits) digits = add_mask(digits, mask) raise AssertionError("Not found")
def problem500(): TARGET = 500500 MODULUS = 500500507 isprime = eulerlib.list_primality( 7376507) # 500500th (1-based) prime number queue = [] nextprime = 2 heapq.heappush(queue, nextprime) ans = 1 for _ in range(TARGET): item = heapq.heappop(queue) ans *= item ans %= MODULUS heapq.heappush(queue, item**2) if item == nextprime: nextprime += 1 while not isprime[nextprime]: nextprime += 1 heapq.heappush(queue, nextprime) return ans
def count_consecutive_primes(a_b): """ count_consecutive_primes for use a key=count_consecutive_primes :param a_b: tuple (a,b) :return: i """ input_a, input_b = a_b i = 0 for i in itertools.count(): intermediate_n = i * i + i * input_a + input_b if not is_prime(intermediate_n): break return i IS_PRIME_CACHE = eulerlib.list_primality(1000) def is_prime(input_n): """ cached version of eulerlib.is_prime :param input_n: :return: """ if input_n < 0: return False if input_n < len(IS_PRIME_CACHE): return IS_PRIME_CACHE[input_n] return eulerlib.is_prime(input_n)
def test_list_primality(input_n, expected_output): output = eulerlib.list_primality(input_n) print(output) assert output == expected_output