Project Euler

Useful Functions


In [17]:
def is_prime(n):
    if n == 1: return False
    if n < 4: return True 
    if n % 2 == 0: return False
    if n < 9: return True # excluded 4, 6, 8 already
    if n % 3 == 0: return False
    i = 5
    while i < n**(0.5) + 1:
        if n % i == 0:
            return False
        if n % (i + 2) == 0:
            return False
        i += 6
    return True

def fibonacci():
    a, b = 0, 1
    while 1:
        yield a
        a, b = b, a + b
        
def triangular():
    current = 1
    counter = 2
    while 1:
        yield current
        current += counter
        counter += 1

def collatz(start):
    current = start
    while 1:
        yield current
        if current == 1:
            break
        if current % 2 == 0:
            current /= 2
        else:
            current = 3 * current + 1
        
def factors(n):    
    result = []
    for i in range(1, int(n ** 0.5) + 1):
        div, mod = divmod(n, i)
        if mod == 0:
            result.extend([i, div])
    return result

def pfactors(n):
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)
    return factors


def is_palindrome(n):
    n = str(n)
    return n == n[::-1]

from math import gcd

def lcm(a, b):
    return a * b // gcd(a, b)

def erat_sieve(m):
    primes = [True] * m
    primes[0] = primes[1] = False
    for i in range(2, m + 1):
        for l in range(2, (m // i) + 1):
            try:
                primes[i * l] = False
            except IndexError: pass
    return [a for a, b in enumerate(primes) if b]

def factorial(n):
    acc = 1
    while n > 1:
        acc *= n
        n -= 1
    return acc

def d(n):
    return sum(set(factors(n))) - n

def is_pandigital(n):
    n = str(n)
    for i in range(len(n)):
        if n.find(str(i + 1)) == -1:
            return False
    return True

def is_triangular(x):
    n = (pow(1 + 8 * x, 0.5) - 1) / 2.0
    d, r = divmod(n, 1)
    return not bool(r)

def is_pentagonal(x):
    n = (pow(1 + 24 * x, 0.5) + 1) / 6.0
    d, r = divmod(n, 1)
    return not bool(r)


def choose(n, r):
    return factorial(n) / (factorial(r) * factorial(n - r) * 1.0)

def is_lychrel(n, max_iterations=50):
    orig = n
    for it in range(max_iterations):
        n = n + int(str(n)[::-1])
        if is_palindrome(n):
            #print(orig, it, False)
            return False
    
    #print(orig, None, True)
    return True

Problem 1

Multiples of 3 and 5

If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.

Find the sum of all the multiples of 3 or 5 below 1000.


In [9]:
def multiples(max_n, a, b):
    s = 0
    for i in range(1, max_n):
        if i % a == 0 or i % b == 0:
            s += i
    return s

print(multiples(1000, 3, 5))


233168

Problem 2

Even Fibonacci numbers

Each new term in the Fibonacci sequence is generated by adding the previous two terms. By starting with 1 and 2, the first 10 terms will be:

1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...

By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.


In [10]:
def even_fibonacci(max_term):
    f = fibonacci()
    current = 0
    total = 0
    while current < max_term:
        current = next(f)
        if current % 2 == 0:
            total += current
    return total

print(even_fibonacci(4000000))


4613732

Problem 3

Largest prime factor

The prime factors of 13195 are 5, 7, 13 and 29.

What is the largest prime factor of the number 600851475143 ?


In [11]:
def largest_prime_factor(n):
    return max(pfactors(n))

print(largest_prime_factor(600851475143))


6857

Problem 4

Largest palindrome product

A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.

Find the largest palindrome made from the product of two 3-digit numbers.

Some thoughts on strategy

Palindrome P = ab, where a and b are the two 3-digit numbers (which much be between 100 and 999).

Since P is palindromic, it can be represented as xyzzyx.

$$ P=100000x + 10000y + 1000z + 100z + 10y + x $$$$ P=100001x + 10010y + 1100z $$$$ P=11(9091x + 910y + 100z) = ab $$

Since 11 is prime, either a or b muct have a factor or 11.


In [12]:
def largest_palindrome_product():
    largest_palindrome = 0
    a = 999
    while a >= 100:
        if a % 11 == 0:
            b = 999
            db = 1
        else:
            b = 990
            db = 11
        while b >= a:
            if a * b <= largest_palindrome:
                break
            
            if is_palindrome(a * b):
                largest_palindrome = a * b
    
            b -= db
        a -= 1
    return largest_palindrome

print(largest_palindrome_product())


906609

Problem 5

Smallest multiple

2520 is the smallest number that can be divided by each of the numbers from 1 to 10 without any remainder.

What is the smallest positive number that is evenly divisible by all of the numbers from 1 to 20?


In [13]:
from functools import reduce

def smallest_multiple(start, end):
    numbers = range(start, end + 1)
    return reduce(lcm, numbers)

print(smallest_multiple(1, 20))


232792560

Problem 6

Sum square difference

The sum of the squares of the first ten natural numbers is,

$$ 1^2 + 2^2 + ... + 10^2 = 385 $$

The square of the sum of the first ten natural numbers is, $$ (1 + 2 + ... + 10)^2 = 552 = 3025 $$ Hence the difference between the sum of the squares of the first ten natural numbers and the square of the sum is $3025 − 385 = 2640$.

Find the difference between the sum of the squares of the first one hundred natural numbers and the square of the sum.


In [14]:
def square_sum(l):
    return sum(l) ** 2

def sum_square(l):
    return sum(x*x for x in l)

def sum_square_difference(n):
    numbers = range(1, n + 1)
    return abs(square_sum(numbers) - sum_square(numbers))

print(sum_square_difference(100))


25164150

Problem 7

10001st prime

By listing the first six prime numbers: 2, 3, 5, 7, 11, and 13, we can see that the 6th prime is 13.

What is the 10 001st prime number?


In [15]:
def nth_prime(n):
    count = 1
    current = 3
    while 1:
        if is_prime(current):
            count += 1
            if count == n:
                return current
        current += 2

print(nth_prime(10001))


104743

Problem 8

Largest product in a series

The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832.

Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product?


In [46]:
def largest_series_product(fname):
    with open(fname) as f:
        thousand_digit_number = f.read()
    tdn = ''.join(thousand_digit_number.split('\n'))
    mul = lambda x, y: int(x) * int(y)
    return max(reduce(mul, tdn[i:i+13]) for i in range(len(tdn)-13+1))

print(largest_series_product('p008_thousand_digits.txt'))


23514624000

Problem 9

Special Pythagorean triplet

A Pythagorean triplet is a set of three natural numbers, $a < b < c$, for which,

$$ a^2 + b^2 = c^2 $$

For example, $3^2 + 4^2 = 9 + 16 = 25 = 5^2$.

There exists exactly one Pythagorean triplet for which $a + b + c = 1000$. Find the product $abc$.


In [17]:
def special_pythagorean_triplet(n):
    for i in range(1, n):
        for j in range(1, n - i):
            if i + j > 1000:
                continue
            k = n - i - j
            if i ** 2 + j ** 2 == k ** 2:
                return i * j * k
    return None

print(special_pythagorean_triplet(1000))


31875000

Problem 10

Summation of primes

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17.

Find the sum of all the primes below two million.


In [18]:
def prime_summation(n):
    return sum(erat_sieve(n))

print(prime_summation(2000000))


142913828922

Problem 11

Largest product in a grid

In the 20×20 grid below, four numbers along a diagonal line have been marked in red.

The product of these numbers is 26 × 63 × 78 × 14 = 1788696.

What is the greatest product of four adjacent numbers in the same direction (up, down, left, right, or diagonally) in the 20×20 grid?


In [48]:
def largest_grid_product(grid, adjacents):
    grid = [[int(i) for i in row.split()] for row in grid.split('\n')]
    m = 0
    product = lambda sl: reduce(lambda a, b: a * b, sl)
    for i in range(len(grid) - adjacents + 1):
        for j in range(len(grid) - adjacents + 1):
            m = max(m, product(grid[i][j:j+adjacents]))
            m = max(m, product([c[j] for c in grid[i:i+adjacents]]))
            
            rdiagonal_product = 1
            for adj in range(adjacents):
                rdiagonal_product *= grid[i+adj][j+adj]
            m = max(m, rdiagonal_product)
            
            if j >= 3 and i <= 17:
                ldiagonal_product = 1
                for adj in range(adjacents):
                    ldiagonal_product *= grid[i+adj][j-adj]
                m = max(m, ldiagonal_product)
    return m

with open('p011_grid.txt') as f:
    print(largest_grid_product(f.read(), 4))


70600674

Problem 12

Highly divisible triangular number

The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

Let us list the factors of the first seven triangle numbers:

 1: 1
 3: 1,3
 6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28

We can see that 28 is the first triangle number to have over five divisors.

What is the value of the first triangle number to have over five hundred divisors?


In [20]:
def divisible_triangular(divisor_count):
    t = triangular()
    current = 1
    while len(factors(current)) < divisor_count:
        current = next(t)
    return current

print(divisible_triangular(500))


76576500

Problem 13

Large sum

Work out the first ten digits of the following one-hundred 50-digit numbers.


In [50]:
def large_sum():
    with open('p013_numbers.txt') as f:
        hundred_50digit_numbers = f.read()
    numbers = [int(n) for n in hundred_50digit_numbers.split('\n')]
    number_sum = sum(numbers)
    return str(number_sum)[:10]

print(large_sum())


5537376230

Problem 14

Longest Collat sequence

The following iterative sequence is defined for the set of positive integers:

n → n/2 (n is even)

n → 3n + 1 (n is odd)

Using the rule above and starting with 13, we generate the following sequence:

13 → 40 → 20 → 10 → 5 → 16 → 8 → 4 → 2 → 1

It can be seen that this sequence (starting at 13 and finishing at 1) contains 10 terms. Although it has not been proved yet (Collatz Problem), it is thought that all starting numbers finish at 1.

Which starting number, under one million, produces the longest chain?

NOTE: Once the chain starts the terms are allowed to go above one million.


In [22]:
def collatz_length(start):
    return len(list(collatz(start)))

def longest_collatz(max_starting):
    previous = {}
    highest, chainlen = 0, 0
    for s in range(max_starting, 0, -1):
        chln = collatz_length(s)
        if chln > chainlen:
            highest, chainlen = s, chln
    return highest
    
print(longest_collatz(1000000))


837799

Problem 15

Lattice paths

Starting in the top left corner of a 2×2 grid, and only being able to move to the right and down, there are exactly 6 routes to the bottom right corner.

How many such routes are there through a 20×20 grid?

Strategy planning

a - b - c - d
|   |   |   | 
e - f - g - h
|   |   |   |
i - j - k - l
|   |   |   |
m - n - o - p

A smaller problem is the number of routes from a to p. We already know that the number of routes from f to p is 6.

At each point we can work out the number of routes to p.

20 - 10 - 4 - 1
|   |   |   | 
10 - 6 - 3 - 1
|   |   |   |
4 - 3 - 2 - 1
|   |   |   |
1 - 1 - 1 - 0

You can see that at any point the number of routes is the sum of the number of routes for below and right. This isn't too difficult to program.


In [23]:
def lattice_paths(size):
    size += 1
    grid = [[None] * size for i in range(size)]
    
    # setup the grid 
    grid[0][0] = 0 
    for i in range(1, size):
        grid[0][i] = 1
        grid[i][0] = 1
    
    # populate the grid
    for r in range(1, size):
        for c in range(1, size):
            grid[r][c] = grid[r-1][c] + grid[r][c-1]
    
    # find the value in the other corner
    return grid[size-1][size-1]

print(lattice_paths(20))


137846528820

Problem 16

Power digit sum

$2^{15} = 32768$ and the sum of its digits is $3 + 2 + 7 + 6 + 8 = 26$.

What is the sum of the digits of the number $2^{1000}$?


In [24]:
def power_digit_sum(base, power):
    return sum(map(int, list(str(base ** power))))

print(power_digit_sum(2, 1000))


1366

Problem 17

Number letter counts

If the numbers 1 to 5 are written out in words: one, two, three, four, five, then there are 3 + 3 + 5 + 4 + 4 = 19 letters used in total.

If all the numbers from 1 to 1000 (one thousand) inclusive were written out in words, how many letters would be used?

NOTE: Do not count spaces or hyphens. For example, 342 (three hundred and forty-two) contains 23 letters and 115 (one hundred and fifteen) contains 20 letters. The use of "and" when writing out numbers is in compliance with British usage.


In [25]:
def number_letter_counts(start, end):
    words = {
        0: '', 1: 'one', 2: 'two', 3: 'three', 4: 'four',
        5: 'five', 6: 'six', 7: 'seven', 8: 'eight', 9: 'nine',
        10: 'ten', 11: 'eleven', 12: 'twelve', 13: 'thirteen', 
        14: 'fourteen', 15: 'fifteen', 16: 'sixteen', 
        17: 'seventeen', 18: 'eighteen', 19: 'nineteen', 
        20: 'twenty', 30: 'thirty', 40: 'forty', 50: 'fifty',
        60: 'sixty', 70: 'seventy', 80: 'eighty', 90: 'ninety',
        1000: 'onethousand', '00': 'hundred', '&': 'and'
    }
    
    def number_count(n):
        ncount = words.get(n)
        if ncount: 
            #print('{n: <6} {w: <30} {c}'.format(n=n, w=ncount, 
            #                                    c=len(ncount)))
            return len(ncount)
        else:
            count = ''
            h, rem = divmod(n, 100)
            if n >= 100:
                count += words.get(h) + words.get('00')
                if rem == 0:
                    #print('{n: <6} {w: <30} {c}'.format(n=n, w=count, c=len(count)))
                    return len(count)
                elif rem <= 20 or rem % 10 == 0:
                    count += words.get('&') + words.get(rem)
                else:
                    t, u = divmod(rem, 10)
                    t = int(str(t) + '0')
                    count += words.get('&') + words.get(t)
                    count += words.get(u)
            else:
                if n <= 20 or n % 10 == 0:
                    count += words.get(n)
                else:
                    t, u = divmod(n, 10)
                    t = int(str(t) + '0')
                    count += words.get(t) + words.get(u)
            #print('{n: <6} {w: <30} {c}'.format(n=n, w=count, c=len(count)))
            return len(count)

    total = 0
    for i in range(start, end + 1):
        total += number_count(i)
    
    return total

print(number_letter_counts(1, 1000))


21124

Problem 18

Maximum path sum I

By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.

3
7 4
2 4 6
8 5 9 3

That is, 3 + 7 + 4 + 9 = 23.

Find the maximum total from top to bottom of the triangle below:

75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23

NOTE: As there are only 16384 routes, it is possible to solve this problem by trying every route. However, Problem 67, is the same challenge with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method!

Strategy

For a triangle with one layer, a solution is trivial - there is only one path.

12

For a triangle with 3 layers, a solution is also trivial - we only need to take the maximum value on the last layer.

88
99 65
41 41 26

We can use the same priciple for the rest of the triangle, by replacing each value with the sum of itself and the maximum of the 2 values below it. Eventually the maximum sum will be the value at the top of the triangle. For the example above, this is demonstrated below.

88 + (99 + 41)
(99 + 41) (65 + 26)
41        41        26

228
140 91
41  41 26

In [26]:
maximum_path_pyramid1 = '''75
95 64
17 47 82
18 35 87 10
20 04 82 47 65
19 01 23 75 03 34
88 02 77 73 07 63 67
99 65 04 28 06 16 70 92
41 41 26 56 83 40 80 70 33
41 48 72 33 47 32 37 16 94 29
53 71 44 65 25 43 91 52 97 51 14
70 11 33 28 77 73 17 78 39 68 17 57
91 71 52 38 17 14 91 43 58 50 27 29 48
63 66 04 68 89 53 67 30 73 16 69 87 40 31
04 62 98 27 23 09 70 98 73 93 38 53 60 04 23'''

def maximum_path_sum(pyramid):
    for row in range(len(pyramid)-1, 0, -1):
        for col in range(0, row):
            pyramid[row-1][col] += max(pyramid[row][col], pyramid[row][col+1])
    return pyramid[0][0]

print(maximum_path_sum([[int(n) for n in row.split()] for row in maximum_path_pyramid1.split('\n')]))


1074

Problem 19

Counting Sundays

You are given the following information, but you may prefer to do some research for yourself.

  • 1 Jan 1900 was a Monday.
  • Thirty days has September, April, June and November. All the rest have thirty-one, Saving February alone, Which has twenty-eight, rain or shine. And on leap years, twenty-nine.
  • A leap year occurs on any year evenly divisible by 4, but not on a century unless it is divisible by 400.

How many Sundays fell on the first of the month during the twentieth century (1 Jan 1901 to 31 Dec 2000)?


In [27]:
from datetime import timedelta, date

def daterange(start_date, end_date):
    for n in range(int ((end_date - start_date).days)):
        yield start_date + timedelta(n)

def counting_sundays(start_date, end_date):
    total = 0
    for d in daterange(start_date, end_date):
        if d.weekday() == 6 and d.day == 1:
            total += 1
    return total


print(counting_sundays(date(1901, 1, 1), date(2000, 12, 31)))


171

Problem 20

Factorial digit sum

n! means n × (n − 1) × ... × 3 × 2 × 1

For example, 10! = 10 × 9 × ... × 3 × 2 × 1 = 3628800, and the sum of the digits in the number 10! is 3 + 6 + 2 + 8 + 8 + 0 + 0 = 27.

Find the sum of the digits in the number 100!


In [28]:
def factorial_digit_sum(n):
    return sum(map(int, list(str(factorial(n)))))

print(factorial_digit_sum(100))


648

Problem 21

Amicable numbers

Let d(n) be defined as the sum of proper divisors of n (numbers less than n which divide evenly into n). If d(a) = b and d(b) = a, where a ≠ b, then a and b are an amicable pair and each of a and b are called amicable numbers.

For example, the proper divisors of 220 are 1, 2, 4, 5, 10, 11, 20, 22, 44, 55 and 110; therefore d(220) = 284. The proper divisors of 284 are 1, 2, 4, 71 and 142; so d(284) = 220.

Evaluate the sum of all the amicable numbers under 10000.


In [29]:
def amicable_numbers(max_n):
    amicables = [False] * max_n
    for a in range(1, max_n):
        if not amicables[a]:
            b = d(a)
            if d(b) == a and a != b:
                amicables[a] = amicables[b] = True
    return sum([i for i, j in enumerate(amicables) if j])

print(amicable_numbers(10000))


31626

Problem 22

Name scores

Using names.txt (right click and 'Save Link/Target As...'), a 46K text file containing over five-thousand first names, begin by sorting it into alphabetical order. Then working out the alphabetical value for each name, multiply this value by its alphabetical position in the list to obtain a name score.

For example, when the list is sorted into alphabetical order, COLIN, which is worth 3 + 15 + 12 + 9 + 14 = 53, is the 938th name in the list. So, COLIN would obtain a score of 938 × 53 = 49714.

What is the total of all the name scores in the file?


In [30]:
def name_scores():
    with open('p022_names.txt') as f:
        names = enumerate(sorted([n.upper().strip('"') for n in f.read().split(',')]))
        
    alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    def name_score(name_tuple):
        place, name = name_tuple
        
        name_value = 0
        for letter in name:
            name_value += alpha.find(letter) + 1
        return name_value * (place + 1)
        
    return sum(map(name_score, list(names)))
        
print(name_scores())


871198282

Problem 23

Non-abundant sums

A perfect number is a number for which the sum of its proper divisors is exactly equal to the number. For example, the sum of the proper divisors of 28 would be 1 + 2 + 4 + 7 + 14 = 28, which means that 28 is a perfect number.

A number n is called deficient if the sum of its proper divisors is less than n and it is called abundant if this sum exceeds n.

As 12 is the smallest abundant number, 1 + 2 + 3 + 4 + 6 = 16, the smallest number that can be written as the sum of two abundant numbers is 24. By mathematical analysis, it can be shown that all integers greater than 28123 can be written as the sum of two abundant numbers. However, this upper limit cannot be reduced any further by analysis even though it is known that the greatest number that cannot be expressed as the sum of two abundant numbers is less than this limit.

Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers.


In [31]:
def non_abundant_sums():
    abundants = set(i for i in range(1, 28124) if d(i) > i)
    def is_abundantsum(n):
        return any(n - a in abundants for a in abundants)
    return sum(j for j in range(1, 28124) if not is_abundantsum(j))

print(non_abundant_sums())


4179871

Problem 24

Lexicographic permutations

A permutation is an ordered arrangement of objects. For example, 3124 is one possible permutation of the digits 1, 2, 3 and 4. If all of the permutations are listed numerically or alphabetically, we call it lexicographic order. The lexicographic permutations of 0, 1 and 2 are:

012 021 102 120 201 210

What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9?


In [32]:
from itertools import permutations

def lexicographic_permutations(digits, index):
    return ''.join(map(str, sorted(list(permutations(digits)))[index - 1]))

print(lexicographic_permutations(range(10), 1000000))


2783915460

Problem 25

1000-digit Fibonacci number

The Fibonacci sequence is defined by the recurrence relation:

Fn = Fn−1 + Fn−2, where F1 = 1 and F2 = 1.

Hence the first 12 terms will be:

F1 = 1
F2 = 1
F3 = 2
F4 = 3
F5 = 5
F6 = 8
F7 = 13
F8 = 21
F9 = 34
F10 = 55
F11 = 89
F12 = 144

The 12th term, F12, is the first term to contain three digits.

What is the index of the first term in the Fibonacci sequence to contain 1000 digits?


In [33]:
import math

def big_fibonacci(digit_count):
    ''' phi ** n / sqrt(5) > 10 ** 999
        n * log(phi) > 999 * log(10) + log(5)/2
        n > (999 * log(10) + log(5) / 2) / log(phi)
    '''
    phi = (1 + 5**0.5)/2
    return math.floor(((999 * math.log(10) + math.log(5) / 2) / math.log(phi)) + 0.5)
    
print(big_fibonacci(1000))


4782

Problem 26

Reciprocal cycles

A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given:

1/2 =   0.5
1/3 =   0.(3)
1/4 =   0.25
1/5 =   0.2
1/6 =   0.1(6)
1/7 =   0.(142857)
1/8 =   0.125
1/9 =   0.(1)
1/10    =   0.1 

Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle.

Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part.

Strategy

Fermat's little theorem says:

1/d has a cycle of $n$ digits if $10^n - 1 \mod d = 0$ for prime $d$

A prime number in the denominator can yield up to d-1 repeating decimal digits, so we need to find the largest prime under 1000 that has d-1 repeating digits.


In [40]:
def reciprocal_cycles(lim):
    for d in erat_sieve(lim)[::-1]:
        period = 1
        while pow(10, period, d) != 1:
            period += 1
        if d - 1 == period:
            return d

print(reciprocal_cycles(1000))


983

Problem 27

Quadratic primes

Euler discovered the remarkable quadratic formula:

$$ n^2+n+41 $$

It turns out that the formula will produce 40 primes for the consecutive integer values $0≤n≤39$. However, when $n=40,40^2+40+41=40(40+1)+41$ is divisible by 41, and certainly when $n=41,41^2+41+41$ is clearly divisible by 41.

The incredible formula $n^2−79n+1601$ was discovered, which produces 80 primes for the consecutive values $0≤n≤79$. The product of the coefficients, −79 and 1601, is −126479.

Considering quadratics of the form:

$n^2+an+b$, where $|a|<1000$ and $|b|≤1000$

where $|n|$ is the modulus/absolute value of $n$ e.g. $|11|=11$ and $|−4|=4$

Find the product of the coefficients, $a$ and $b$, for the quadratic expression that produces the maximum number of primes for consecutive values of $n$, starting with $n=0$.

Strategy

  • $|b|$ must be prime, since $n=0$ must result in a prime.
  • If for a combination (a, b), we get m consecutive primes, it must be true that b > m.
  • When $a < 0$, then $b > -(n^2 + an)$, because the primes must be positive. We know that $n^2 + n + 41$ returns 40 primes, interesting values for $a$ and $b$ should satisfy $b > =(40^2 + 40a)$.

In [42]:
def quadratic_primes(lim):
    besta = bestb = max_res= 0
    for a in range(-1000, 1001):
        for b in erat_sieve(1000):
            if b < -(pow(40, 2) + 40 * a) or b < max_res:
                continue
            res = n = 0
            while is_prime(pow(n, 2) + a * n + b):
                res += 1
                n += 1
            if res > max_res:
                besta, bestb, max_res = a, b, res
    #print(besta, bestb, max_res)
    return besta * bestb

print(quadratic_primes(1000))


-61 971 71
-59231

Problem 28

Number spiral diagonals

Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows:

21 22 23 24 25
20  7  8  9 10
19  6  1  2 11
18  5  4  3 12
17 16 15 14 13

It can be verified that the sum of the numbers on the diagonals is 101.

What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way?


In [34]:
def number_spiral_diagonals(size):
    total = 1
    counter = 1
    skip = 2
    while counter < size * size:
        for i in range(4):
            counter += skip
            total += counter
        skip += 2
    return total

print(number_spiral_diagonals(1001))


669171001

Problem 29

Distinct powers

Consider all integer combinations of $a^b$ for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5

If they are then placed in numerical order, with any repeats removed, we get the following sequence of 15 distinct terms:

4, 8, 9, 16, 25, 27, 32, 64, 81, 125, 243, 256, 625, 1024, 3125

How many distinct terms are in the sequence generated by ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100?


In [35]:
from itertools import product

def distinct_powers(a_range):
    power = lambda t: pow(t[0], t[1])
    terms = set(map(power, product(a_range, repeat=2)))
    return len(terms)
    
print(distinct_powers(range(2, 101)))


9183

Problem 35

Circular primes

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?


In [36]:
from itertools import permutations

def circular_primes(max_n):
    def rotations(n):
        rots = [n]
        n = str(n)
        for i in range(len(n) - 1):
            n = n[1:] + n[0]
            rots.append(int(n))
        return rots
    
    cp = set()
    cp.add(2)
    for i in range(3, max_n, 2):
        if all(map(is_prime, rotations(i))):
            cp.add(i)
    return len(cp)

print(circular_primes(1000000))


55

Problem 37

Truncatable primes

The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3.

Find the sum of the only eleven primes that are both truncatable from left to right and right to left.

NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes.


In [37]:
'''
Last digit can be 3 or 7. First can be 2, 3, 5 or 7

Possible numbers:
    -13
    -17
    -37
    -73
    -97
    
Actual values:

23
37
73
53
57

if has 2 or 5 as not the first digit, then reject

'''

from itertools import product, chain

def primely_truncatable(n):
    n = int(n)
    def left_truncate(l):
        ns = str(l)[1:]
        if len(ns) == 0:
            return True
        else:
            if is_prime(int(ns)):
                return left_truncate(int(ns))
            return False
        
    def right_truncate(r):
        ns = str(r)[:-1]
        if len(ns) == 0:
            return True
        else:
            if is_prime(int(ns)):
                return right_truncate(int(ns))
            return False
        
    if is_prime(n):
        l, r = left_truncate(n), right_truncate(n)
        return l and r

    return False


def get_truncatables():
    primes = [13, 17, 37, 73, 97]
    additional = [2, 3, 5, 7, 9]
    working = []
    result = [23, 37, 73, 53]
    
    nlen = 2
        
    while len(result) < 11 and nlen < 7:
        ptuple = chain(product(additional, primes),product(primes, additional))
        for p in ptuple:
            if 2 in p[1:] or 5 in p[1:]:
                continue
            p = ''.join(map(str, p))
            if primely_truncatable(p):
                result.append(int(p))
            if is_prime(int(p)):
                working.append(int(p))
        result = list(set(result))
        primes = working
        nlen += 1
    
    return result

double_truncatables = get_truncatables()
print(double_truncatables)
print(sum(double_truncatables))


[3137, 37, 739397, 73, 373, 53, 23, 3797, 313, 317, 797]
748317

Problem 41

Pandigital prime

We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital and is also prime.

What is the largest n-digit pandigital prime that exists?


In [10]:
from itertools import permutations

def pandigital_prime(n_digits):
    if n_digits == 0:
        return False
    digits = [1, 2, 3, 4, 5, 6, 7, 8, 9][::-1]
    pandigitals = permutations(digits[9-n_digits:10])
    for i in pandigitals:
        n = int(''.join(map(str, i)))
        if is_prime(n):
            return n
    return pandigital_prime(n_digits-1)

print(pandigital_prime(9))


7652413

Problem 42

Coded triangle numbers

The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are:

1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...

By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. For example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word value is a triangle number then we shall call the word a triangle word.

Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, how many are triangle words?


In [34]:
def coded_triangles(fname):
    def score(w):
        alpha = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        total = 0
        for letter in w:
            total += alpha.find(letter) + 1
        return total
        
    with open(fname) as f:
        words = [w.strip('"') for w in f.read().split(',')]
        
    ct_words = [w for w in words if is_triangular(score(w))]
    return len(ct_words)

print(coded_triangles('p042_words.txt'))


162

Problem 43

Sub-string divisibility

The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a rather interesting sub-string divisibility property.

Let $d_1$ be the 1st digit, $d_2$ be the 2nd digit, and so on. In this way, we note the following:

  • $d_2d_3d_4=406$ is divisible by 2
  • $d_3d_4d_5=063$ is divisible by 3
  • $d_4d_5d_6=635$ is divisible by 5
  • $d_5d_6d_7=357$ is divisible by 7
  • $d_6d_7d_8=572$ is divisible by 11
  • $d_7d_8d_9=728$ is divisible by 13
  • $d_8d_9d_{10}=289$ is divisible by 17

Find the sum of all 0 to 9 pandigital numbers with this property.


In [28]:
from itertools import permutations

def sub_string_divisible():
    primes = [2, 3, 5, 7, 11, 13, 17]
    def is_ssd(tup):
        for d in range(1, len(tup) - 2):
            n = int(''.join(map(str, tup[d:d+3])))
            if n % primes[d-1] != 0:
                return False
        return True
    
    digits = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    ssds = [int(''.join(map(str, i))) for i in permutations(digits) if is_ssd(i)]
    #print(ssds)
    return sum(ssds)
    

print(sub_string_divisible())


[1406357289, 1430952867, 1460357289, 4106357289, 4130952867, 4160357289]
16695334890

Problem 44

Pentagonal numbers

Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first ten pentagonal numbers are:

1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ...

It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 − 22 = 48, is not pentagonal.

Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference are pentagonal and D = |Pk − Pj| is minimised; what is the value of D?


In [8]:
def pentagonal_numbers():
    res = 0
    found = False
    i = 1
    while not found:
        i += 1
        n = i * (3 * i - 1) / 2
        
        for j in range(i - 1, 0, -1):
            m = j * (3 * j - 1) / 2
            if is_pentagonal(abs(n - m)) and is_pentagonal(n + m):
                res = abs(n - m)
                found = True
                break
    return int(res)

print(pentagonal_numbers())


5482660

Problem 45

Triangular, pentagonal, and hexagonal

Triangle, pentagonal, and hexagonal numbers are generated by the following formulae:

Triangle: $T_n=n(n+1)/2$ --> 1, 3, 6, 10, 15, ...

Pentagonal: $P_n=n(3n−1)/2$ --> 1, 5, 12, 22, 35, ...

Hexagonal: $H_n=n(2n−1)$ --> 1, 6, 15, 28, 45, ...

It can be verified that $T_{285}$ = $P_{165}$ = $H_{143}$ = 40755.

Find the next triangle number that is also pentagonal and hexagonal.

Strategy

Obviously all hexagonal numbers are also triangular, so we only need to find overlap of hexagonals and pentagonals, and we can start at $H_{143}$.


In [12]:
def tph(h_n):
    def h(n):
        return n * (2 * n - 1)
    h_n += 1
    current = h(h_n)
    while not is_pentagonal(current):
        h_n += 1
        current = h(h_n)
    return current
    
print(tph(143))


1533776805

Problem 46

Goldbach's other conjecture

It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square.

$9 = 7 + 2×1^2$

$15 = 7 + 2×2^2$

$21 = 3 + 2×3^2$

$25 = 7 + 2×3^2$

$27 = 19 + 2×2^2$

$33 = 31 + 2×1^2$

It turns out that the conjecture was false.

What is the smallest odd composite that cannot be written as the sum of a prime and twice a square?

A composite number is any number greater than 1, which is not prime.


In [51]:
def goldbachs_other_conjecture():
    n = 5
    primes = set()
    while 1:
        if (all(n % p for p in primes)):
            primes.add(n)
        else:
            if not any((n - 2 * i * i) in primes for i in range(1, n)):
                return n
        n += 2

print(goldbachs_other_conjecture())


5777

Problem 47

Distinct prime factors

The first two consecutive numbers to have two distinct prime factors are:

14 = 2 × 7

15 = 3 × 5

The first three consecutive numbers to have three distinct prime factors are:

644 = 2² × 7 × 23

645 = 3 × 5 × 43

646 = 2 × 17 × 19.

Find the first four consecutive integers to have four distinct prime factors. What is the first of these numbers?


In [56]:
def distinct_prime_factors(starting_number, consecutive_numbers, distinct_factors):
    def has_distinct_factors(n):
        return len(set(pfactors(n))) == distinct_factors
    
    numbers = [starting_number + i for i in range(consecutive_numbers)]
    while not all(map(has_distinct_factors, numbers)):
        numbers = [n + 1 for n in numbers]
    print(numbers)
    return numbers[0]

print(distinct_prime_factors(2*3*5*7, 4, 4))


[134043, 134044, 134045, 134046]
134043

Problem 48

Self powers

The series, 1^1 + 2^2 + 3^3 + ... + 10^10 = 10405071317.

Find the last ten digits of the series, 1^1 + 2^2 + 3^3 + ... + 1000^1000.


In [76]:
def self_powers(series_end):
    return str(sum(pow(i, i) for i in range(1, series_end + 1)))[-10:]

print(self_powers(1000))


9110846700

Problem 49

Prime permutations

The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, and, (ii) each of the 4-digit numbers are permutations of one another.

There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit increasing sequence.

What 12-digit number do you form by concatenating the three terms in this sequence?


In [81]:
def prime_permuations():
    diff = 3330
    res = []
    poss = []
    for i in range(1001, 3333, 2):
        if is_prime(i):
            idigits = sorted(list(str(i)))
            poss.append(i)
            for c in range(2):
                i += diff
                if is_prime(i) and sorted(list(str(i))) == idigits:
                    poss.append(i)
                else:
                    poss = []
                    break
            if poss:
                res.append(poss)
    #return res 
    # slightly odd result here with an extra value, but it's 
    # obvious as to the answer.
    
    return ''.join(list(map(str, res[1]))[:-1])
                    
print(prime_permuations())


296962999629

Problem 50

Consecutive prime sum

The prime 41, can be written as the sum of six consecutive primes: 41 = 2 + 3 + 5 + 7 + 11 + 13

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

The longest sum 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 sum of the most consecutive primes?

Strategy

  • Need to find out which prime to start with, and how many primes to add.
  • Build an array of sums of primes, and then search it to find the highest one.

In [75]:
def consecutive_prime_sum(lim):
    
    result, prime_count = 0, 0
    primes = erat_sieve(lim // 100) # won't actually need that many primes
    
    prime_sum = [0]
    for p in primes:
        prime_sum.append(prime_sum[-1] + p)
        if prime_sum[-1] >= lim: break
    c = len(prime_sum)

    terms = 1
    for i in range(c):
        for j in range(c-1, i+terms, -1):
            n = prime_sum[j] - prime_sum[i]
            if (j-i > terms and is_prime(n)):
                terms, max_prime = j-i, n
                break
    #return terms, max_prime
    return max_prime

print(consecutive_prime_sum(1000000))


(543, 997651)

Problem 52

Permuted multiples

It can be seen that the number, 125874, and its double, 251748, contain exactly the same digits, but in a different order.

Find the smallest positive integer, x, such that 2x, 3x, 4x, 5x, and 6x, contain the same digits.


In [2]:
def permuted_multiples():
    result = None
    for i in range(100000, 200000):
        comp = sorted(list(str(i)))
        success = True
        for mult in range(2, 7):
            if sorted(list(str(i * mult))) != comp:
                success = False
        if success:
            return i

print(permuted_multiples())


142857

Problem 53 [NOT CHECKED]

Combinatoric selections

There are exactly ten ways of selecting three from five, 12345:

123, 124, 125, 134, 135, 145, 234, 235, 245, and 345

In combinatorics, we use the notation, $^5C_3$ = 10.

In general, $$ ^nC_r = \frac{n!}{r!(n−r)!} $$

where r ≤ n, n! = n×(n−1)×...×3×2×1, and 0! = 1.

It is not until n = 23, that a value exceeds one-million: $^{23}C_{10}$ = 1144066.

How many, not necessarily distinct, values of $^nC_r$, for 1 ≤ n ≤ 100, are greater than one-million?

Strategy

  • We know that the it is only at 23c10 that the value exceeds 1000000, so we don't need to start looking until then.
  • If r = 1 or n-1, nCr = n. If r = n, nCr = 1. So we should only look at values of r where 2 <= r <= n-2.

In [8]:
def combinatoric_selections(max_n, min_val):
    values = []
    for n in range(23, max_n + 1):
        for r in range(2, n - 1):
            nCr = choose(n, r)
            if nCr > min_val:
                values.append((n, r, nCr))
    #print(values)
    return len(values)

print(combinatoric_selections(100, 1000000))


4075

Problem 55

Lychrel numbers

If we take 47, reverse and add, 47 + 74 = 121, which is palindromic.

Not all numbers produce palindromes so quickly. For example,

  • 349 + 943 = 1292
  • 1292 + 2921 = 4213
  • 4213 + 3124 = 7337

That is, 349 took three iterations to arrive at a palindrome.

Although no one has proved it yet, it is thought that some numbers, like 196, never produce a palindrome. A number that never forms a palindrome through the reverse and add process is called a Lychrel number. Due to the theoretical nature of these numbers, and for the purpose of this problem, we shall assume that a number is Lychrel until proven otherwise. In addition you are given that for every number below ten-thousand, it will either (i) become a palindrome in less than fifty iterations, or, (ii) no one, with all the computing power that exists, has managed so far to map it to a palindrome. In fact, 10677 is the first number to be shown to require over fifty iterations before producing a palindrome: 4668731596684224866951378664 (53 iterations, 28-digits).

Surprisingly, there are palindromic numbers that are themselves Lychrel numbers; the first example is 4994.

How many Lychrel numbers are there below ten-thousand?

NOTE: Wording was modified slightly on 24 April 2007 to emphasise the theoretical nature of Lychrel numbers.


In [20]:
def lychrel_numbers(max_n):
    return len([i for i in range(max_n) if is_lychrel(i, 50)])

print(lychrel_numbers(10000))


249

Problem 56

Powerful digit sum

A googol ($10^{100}$) is a massive number: one followed by one-hundred zeros; $100^{100}$ is almost unimaginably large: one followed by two-hundred zeros. Despite their size, the sum of the digits in each number is only 1.

Considering natural numbers of the form, $a^b$, where $a$, $b$ < 100, what is the maximum digital sum?


In [24]:
def powerful_digit_sum(max_ab):
    def digit_sum(n):
        return sum(int(i) for i in list(str(n)))
    
    s = 0   
    all_digit_sums = []
    for a in range(100):
        for b in range(100):
            d = digit_sum(pow(a, b))
            all_digit_sums.append((a, b, d))
    #print(all_digit_sums)
    return max(d for a, b, d in all_digit_sums)

print(powerful_digit_sum(100))


972

Problem 58

Spiral primes

Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.

37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18  5  4  3 12 29
40 19  6  1  2 11 28
41 20  7  8  9 10 27
42 21 22 23 24 25 26
43 44 45 46 47 48 49

It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that 8 out of the 13 numbers lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.

If one complete new layer is wrapped around the spiral above, a square spiral with side length 9 will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?


In [ ]:
def spiral_primes(ratio_limit):
    
    ratio = 1
    n = 1
    step = 2
    side_length = 1
    diagonal_count = 1.0
    
    prime_count = 0
    
    while ratio >= ratio_limit:
        diagonal_count += 4
        side_length += 2
        for i in range(4):
            n += step
            if is_prime(n):
                prime_count += 1
                
        ratio = prime_count / diagonal_count
        #print((side_length, prime_count, diagonal_count, ratio))
        step += 2
        
    return side_length

print(spiral_primes(0.1))

Problem 67

Maximum path sum II

This is the same as Problem 18, so the code it reused.

By starting at the top of the triangle below and moving to adjacent numbers on the row below, the maximum total from top to bottom is 23.

3 7 4 2 4 6 8 5 9 3

That is, 3 + 7 + 4 + 9 = 23.

Find the maximum total from top to bottom in triangle.txt, a 15K text file containing a triangle with one-hundred rows.


In [38]:
with open('p067_triangle.txt') as f:
    print(maximum_path_sum([[int(n) for n in s.split()] for s in f.readlines()]))


7273

In [ ]: