diff --git a/e001.py b/e001.py index 272f0ed..9755089 100644 --- a/e001.py +++ b/e001.py @@ -1,6 +1,15 @@ -total = 0 -for x in range(1000): - if (0 == x % 3) or (0 == x % 5): - total = total + x +"""Add all the natural numbers below one thousand that are multiples of 3 or 5. -print 'Answer', total +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. +""" + +def main(): + total = 0 + for x in range(1000): + if (0 == x % 3) or (0 == x % 5): + total = total + x + print 'Answer', total + +if __name__ == '__main__': + main() diff --git a/e002.py b/e002.py index 9fba898..5ff425f 100644 --- a/e002.py +++ b/e002.py @@ -1,17 +1,23 @@ -# -*- coding: utf-8 -*- -# 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, ... -# Find the sum of all the even-valued terms in the sequence which do not exceed four million. +"""Find the sum of all the even-valued terms in the Fibonacci sequence which do not exceed four million. -limit = 4000000 -#limit = 90 -last = [0, 1] -x = 1 -total = 0 -while (x < limit): - if (0 == x % 2): - total += x - last.append(x) - last = last[-2:] - x = sum(last) -print 'Answer', total \ No newline at end of file +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, ... +Find the sum of all the even-valued terms in the sequence which do not exceed four million. +""" + +def main(): + limit = 4000000 + #limit = 90 + last = [0, 1] + x = 1 + total = 0 + while (x < limit): + if (0 == x % 2): + total += x + last.append(x) + last = last[-2:] + x = sum(last) + print 'Answer', total + +if __name__ == '__main__': + main() diff --git a/e003.py b/e003.py index fd29eee..d8c6409 100644 --- a/e003.py +++ b/e003.py @@ -1,3 +1,9 @@ +"""Find the largest prime factor of a composite number. + +The prime factors of 13195 are 5, 7, 13 and 29. +What is the largest prime factor of the number 600851475143 ? +""" + def pfactor(n): i = 2 while (n % i != 0 and i < n): @@ -8,6 +14,9 @@ def pfactor(n): p.append(i) return sorted(p, reverse=True) -if __name__ == '__main__': +def main(): print 'Prime factors of 600851475143:' print pfactor(600851475143) + +if __name__ == '__main__': + main() diff --git a/e004.py b/e004.py index 3ee4745..c23a500 100644 --- a/e004.py +++ b/e004.py @@ -1,3 +1,9 @@ +"""Find the largest palindrome made from the product of two 3-digit numbers. + +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. +""" + def palindrome(): palindromes = {} for i in range(999, 99, -1): @@ -7,5 +13,8 @@ def palindrome(): palindromes[i * ii] = [i, ii] p = sorted(palindromes.keys(), reverse=True)[0] print 'Palindrome: {0}x{1}: {2}'.format(palindromes[p][0], palindromes[p][1], p) -if __name__ == '__main__': +def main(): palindrome() + +if __name__ == '__main__': + main() diff --git a/e005.py b/e005.py index 4f7318d..e4ba125 100644 --- a/e005.py +++ b/e005.py @@ -1,3 +1,9 @@ +"""What is the smallest number divisible by each of the numbers 1 to 20? + +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 number that is evenly divisible by all of the numbers from 1 to 20? +""" + def divisible(n): i = 0 while True: @@ -8,5 +14,8 @@ def divisible(n): break if ii == 1: return x -if __name__ == '__main__': +def main(): print 'Smallest number: ', divisible(20) + +if __name__ == '__main__': + main() diff --git a/e006.py b/e006.py index 1470d52..2e2b484 100644 --- a/e006.py +++ b/e006.py @@ -1,3 +1,13 @@ +"""What is the difference between the sum of the squares and the square of the sums? + +The sum of the squares of the first ten natural numbers is, + 12 + 22 + ... + 102 = 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. +""" + def squarediff(n): print 'Checking for n =', n sumofsquares = sum([x**2 for x in range(n + 1)]) @@ -6,6 +16,9 @@ def squarediff(n): print 'Square of sum', squareofsum print 'Difference', squareofsum - sumofsquares -if __name__ == '__main__': +def main(): squarediff(10) squarediff(100) + +if __name__ == '__main__': + main() diff --git a/e007.py b/e007.py index c3724e8..9e95673 100644 --- a/e007.py +++ b/e007.py @@ -1,3 +1,9 @@ +"""Find the 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 10001st prime number? +""" + import math def is_prime(n): @@ -32,6 +38,9 @@ def primes(max_count = 0, max_value = 0): primes.append(i) return primes -if __name__ == '__main__': +def main(): print '6th Prime', primes(6)[-1] print '10001st Prime', primes(10001)[-1] + +if __name__ == '__main__': + main() diff --git a/e008.py b/e008.py index f74514e..b91e5cc 100644 --- a/e008.py +++ b/e008.py @@ -1,3 +1,5 @@ +"""Discover the largest product of five consecutive digits in the 1000-digit number.""" + NUMBER = """ 73167176531330624919225119674426574742355349194934 96983520312774506326239578318016984801869478851843 @@ -21,14 +23,18 @@ NUMBER = """ 71636269561882670428252483600823257530420752963450 """.replace('\n', '') -max = 0 -set = None -for i in range(len(NUMBER) - 4): - product = 1 - for ii in [int(n) for n in NUMBER[i:i+5]]: - product = product * ii - if product > max: - max = product - set = NUMBER[i:i+5] +def main(): + max = 0 + set = None + for i in range(len(NUMBER) - 4): + product = 1 + for ii in [int(n) for n in NUMBER[i:i+5]]: + product = product * ii + if product > max: + max = product + set = NUMBER[i:i+5] + + print 'Max product is {0} from {1}'.format(max, set) -print 'Max product is {0} from {1}'.format(max, set) +if __name__ == '__main__': + main() diff --git a/e009.py b/e009.py index a840583..cfb2525 100644 --- a/e009.py +++ b/e009.py @@ -1,9 +1,23 @@ +"""Find the only Pythagorean triplet, {a, b, c}, for which a + b + c = 1000. + +A Pythagorean triplet is a set of three natural numbers, a b c, for which, + a2 + b2 = c2 +For example, 32 + 42 = 9 + 16 = 25 = 52. + +There exists exactly one Pythagorean triplet for which a + b + c = 1000. +Find the product abc. +""" + TRIPLET_SUM = 1000 -for c in range(TRIPLET_SUM - 3, 3, -2): - diff = TRIPLET_SUM - c - for x in range(1, int(diff / 2) + 1): - (a, b) = (x, diff - x) - if a**2 + b**2 == c**2: - print '{a}**2 + {b}**2 == {c}**2'.format(a=a, b=b, c=c) - print 'Product: ', a*b*c +def main(): + for c in range(TRIPLET_SUM - 3, 3, -2): + diff = TRIPLET_SUM - c + for x in range(1, int(diff / 2) + 1): + (a, b) = (x, diff - x) + if a**2 + b**2 == c**2: + print '{a}**2 + {b}**2 == {c}**2'.format(a=a, b=b, c=c) + print 'Product: ', a*b*c + +if __name__ == '__main__': + main() diff --git a/e010.py b/e010.py index 7424845..c35677d 100644 --- a/e010.py +++ b/e010.py @@ -1,5 +1,15 @@ +"""Calculate the sum of all the primes below two million. + +The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. +Find the sum of all the primes below two million. +""" + from e007 import primes; -print 'Fetching all primes for n < 2,000,000' -p = primes(0, 2000000) -print 'Sum:', sum(p) +def main(): + print 'Fetching all primes for n < 2,000,000' + p = primes(0, 2000000) + print 'Sum:', sum(p) + +if __name__ == '__main__': + main() diff --git a/e011.py b/e011.py index 8fe0ea6..0b9ed40 100644 --- a/e011.py +++ b/e011.py @@ -1,3 +1,33 @@ +"""What is the greatest product of four numbers on the same straight line in the 20 by 20 grid? + +In the 2020 grid below, four numbers along a diagonal line have been marked in red. + +08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 +49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 +81 49 31 73 55 79 14 29 93 71 40 67 53 88 30 03 49 13 36 65 +52 70 95 23 04 60 11 42 69 24 68 56 01 32 56 71 37 02 36 91 +22 31 16 71 51 67 63 89 41 92 36 54 22 40 40 28 66 33 13 80 +24 47 32 60 99 03 45 02 44 75 33 53 78 36 84 20 35 17 12 50 +32 98 81 28 64 23 67 10[26]38 40 67 59 54 70 66 18 38 64 70 +67 26 20 68 02 62 12 20 95[63]94 39 63 08 40 91 66 49 94 21 +24 55 58 05 66 73 99 26 97 17[78]78 96 83 14 88 34 89 63 72 +21 36 23 09 75 00 76 44 20 45 35[14]00 61 33 97 34 31 33 95 +78 17 53 28 22 75 31 67 15 94 03 80 04 62 16 14 09 53 56 92 +16 39 05 42 96 35 31 47 55 58 88 24 00 17 54 24 36 29 85 57 +86 56 00 48 35 71 89 07 05 44 44 37 44 60 21 58 51 54 17 58 +19 80 81 68 05 94 47 69 28 73 92 13 86 52 17 77 04 89 55 40 +04 52 08 83 97 35 99 16 07 97 57 32 16 26 26 79 33 27 98 66 +88 36 68 87 57 62 20 72 03 46 33 67 46 55 12 32 63 93 53 69 +04 42 16 73 38 25 39 11 24 94 72 18 08 46 29 32 40 62 76 36 +20 69 36 41 72 30 23 88 34 62 99 69 82 67 59 85 74 04 36 16 +20 73 35 29 78 31 90 01 74 31 49 71 48 86 81 16 23 57 05 54 +01 70 54 71 83 51 54 69 16 92 33 48 61 43 52 01 89 19 67 48 + +The product of these numbers is 26 63 78 14 = 1788696. + +What is the greatest product of four adjacent numbers in any direction (up, down, left, right, or diagonally) in the 2020 grid? +""" + GRID = """ 08 02 22 97 38 15 00 40 00 75 04 05 07 78 52 12 50 77 91 08 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00 @@ -22,54 +52,58 @@ GRID = """ """.strip().replace('\n', ' ').split(' ') GRID = [int(n) for n in GRID] -max = 0 -info = None - def product(l): p = 1 for n in l: p = p * n return p -for row in range(1,20): - for col in range(20): - pos = 20 * row + col - - if col <= 16: - # Horizontal - r = GRID[pos:pos+4] - x = product(r) - if x > max: - max = x - info = [col, row, '-', r] - if row <= 16: - # Vertical - r = [] - for i in range(4): - r.append(GRID[pos + 20 * i]) - x = product(r) - if x > max: - max = x - info = [col, row, '|', r] +def main(): + max = 0 + info = None + + for row in range(1,20): + for col in range(20): + pos = 20 * row + col if col <= 16: - # Diagonal (\) - r = [] - for i in range(4): - r.append(GRID[pos + 20 * i + i]) + # Horizontal + r = GRID[pos:pos+4] x = product(r) if x > max: max = x - info = [col, row, '\\', r] - if col >= 3: - # Diagonal (/) + info = [col, row, '-', r] + if row <= 16: + # Vertical r = [] for i in range(4): - r.append(GRID[pos + 20 * i - i]) + r.append(GRID[pos + 20 * i]) x = product(r) if x > max: max = x - info = [col, row, '/', r] + info = [col, row, '|', r] + + if col <= 16: + # Diagonal (\) + r = [] + for i in range(4): + r.append(GRID[pos + 20 * i + i]) + x = product(r) + if x > max: + max = x + info = [col, row, '\\', r] + if col >= 3: + # Diagonal (/) + r = [] + for i in range(4): + r.append(GRID[pos + 20 * i - i]) + x = product(r) + if x > max: + max = x + info = [col, row, '/', r] + + (col, row, direction, l) = info + print 'Max Product is {p} at row {row}, col {col} ({d}): {l}'.format(p=max, row=row, col=col, d=direction, l=l) -(col, row, direction, l) = info -print 'Max Product is {p} at row {row}, col {col} ({d}): {l}'.format(p=max, row=row, col=col, d=direction, l=l) \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/e012.py b/e012.py index 5fe90ab..f62a8d8 100644 --- a/e012.py +++ b/e012.py @@ -1,3 +1,22 @@ +"""What is the value of the first triangle number to have over five hundred divisors? + +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? +""" + from e003 import pfactor from p054.poker import unique_combinations @@ -44,7 +63,7 @@ def factor(n): factors.append(n) return sorted(set(factors)) -if __name__ == '__main__': +def main(): i = 1 while True: i = i + 1 @@ -54,4 +73,6 @@ if __name__ == '__main__': if len(f) > 500: break - print 'Triangle number {0} has {1} factors ({2})'.format(t, len(f), f) \ No newline at end of file + print 'Triangle number {0} has {1} factors ({2})'.format(t, len(f), f) +if __name__ == '__main__': + main() diff --git a/e013.py b/e013.py index 65a96aa..42ef7a6 100644 --- a/e013.py +++ b/e013.py @@ -1,3 +1,5 @@ +"""Find the first ten digits of the sum of one-hundred 50-digit numbers.""" + NUMBERS = """ 37107287533902102798797998220837590246510135740250 46376937677490009712648124896970078050417018260538 @@ -103,6 +105,10 @@ NUMBERS = """ NUMBERS = [int(n) for n in NUMBERS] -s = sum(NUMBERS) -print 'Sum:', s -print 'First 10 Digits:', str(s)[:10] \ No newline at end of file +def main(): + s = sum(NUMBERS) + print 'Sum:', s + print 'First 10 Digits:', str(s)[:10] + +if __name__ == '__main__': + main() diff --git a/e014.py b/e014.py index ebde863..3623bf4 100644 --- a/e014.py +++ b/e014.py @@ -1,3 +1,19 @@ +"""Find the longest sequence using a starting number under one million. + +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. +""" + def collatz(n): steps = 0 while n > 1: @@ -8,13 +24,17 @@ def collatz(n): n = n / 2 return steps -i = 1000000 -max = 0 -maxnum = i -while i > 1: - i = i - 1 - c = collatz(i) - if c > max: - max = c - maxnum = i -print 'Max was {0} steps for {1}'.format(max, maxnum) +def main(): + i = 1000000 + max = 0 + maxnum = i + while i > 1: + i = i - 1 + c = collatz(i) + if c > max: + max = c + maxnum = i + print 'Max was {0} steps for {1}'.format(max, maxnum) + +if __name__ == '__main__': + main() diff --git a/e015.py b/e015.py index d20a635..6264291 100644 --- a/e015.py +++ b/e015.py @@ -1,4 +1,13 @@ +"""Starting in the top left corner in a 20 by 20 grid, how many routes are there to the bottom right corner? + +Starting in the top left corner of a 22 grid, there are 6 routes (without backtracking) to the bottom right corner. + [See: p015/p_015.gif] + +How many routes are there through a 2020 grid? """ + +"""Notes: + Calculate the number of possible paths from the top left corner to the bottom right, without backtracking (no moving up or left) @@ -26,8 +35,11 @@ def pascal(row, col): def paths(size): return pascal(size + (size - 2), size - 1) -if __name__ == '__main__': +def main(): # 20x20 grid # Points = cubes + 1 size = 21 print 'Paths: ', paths(size) + +if __name__ == '__main__': + main() diff --git a/e016.py b/e016.py index ea9091e..ba1d6c3 100644 --- a/e016.py +++ b/e016.py @@ -1,7 +1,17 @@ +"""What is the sum of the digits of the number 21000? + +215 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26. +What is the sum of the digits of the number 21000? +""" + n = 2**1000 -s = str(n) -total = 0 -for c in s: - total = total + int(c) -print 'Sum of digits for {0}: {1}'.format(n, total) +def main(): + s = str(n) + total = 0 + for c in s: + total = total + int(c) + print 'Sum of digits for {0}: {1}'.format(n, total) + +if __name__ == '__main__': + main() diff --git a/e017.py b/e017.py index 6f26b1b..0063fb0 100644 --- a/e017.py +++ b/e017.py @@ -1,3 +1,11 @@ +"""How many letters would be needed to write all the numbers in words from 1 to 1000? + +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. +""" + NUMBERS = [ '', 'one', @@ -54,8 +62,11 @@ def format(n): s.append(NUMBERS[nn % 10]) return ' '.join(s) -if __name__ == '__main__': +def main(): chars = [] for i in range(1, 1001): chars = chars + list(format(i).replace(' ', '').replace('-', '')) print 'Chars:', len(chars) + +if __name__ == '__main__': + main() diff --git a/e018.py b/e018.py index ef89a2a..0547355 100644 --- a/e018.py +++ b/e018.py @@ -1,3 +1,35 @@ +"""Find the maximum sum travelling from the top of the triangle to the base. + +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! ;o) +""" + from e012 import triangle class Vertex: @@ -81,7 +113,7 @@ class Triangle: path.append(v) return path -if __name__ == '__main__': +def main(): vertex_data = [] with open('p018/triangle.txt', 'r') as f: while True: @@ -94,3 +126,6 @@ if __name__ == '__main__': path = t.get_path() print 'Path', [v.value for v in path] print 'Sum', sum([v.value for v in path]) + +if __name__ == '__main__': + main() diff --git a/e019.py b/e019.py index 078e558..d7d2e35 100644 --- a/e019.py +++ b/e019.py @@ -1,3 +1,19 @@ +"""How many Sundays fell on the first of the month during the twentieth century? + +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)? +""" + class Day: SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY = range(7) @@ -28,3 +44,6 @@ while year < 2000: total = total + 1 print 'Total months beginning on Sunday from 1/1/1901 to 12/31/2000: {0}'.format(total) + +if __name__ == '__main__': + main() diff --git a/e020.py b/e020.py index a879cec..ac577dc 100644 --- a/e020.py +++ b/e020.py @@ -1,3 +1,9 @@ +"""Find the sum of digits in 100! + +n! means n (n 1) ... 3 2 1 +Find the sum of the digits in the number 100! +""" + # Could use math.factorial, but that takes the fun out of it, doesn it def factorial(n): f = n @@ -7,9 +13,13 @@ def factorial(n): i = i - 1 return f -f = str(factorial(100)) -sum = 0 -for c in f: - sum = sum + int(c) +def main(): + f = str(factorial(100)) + sum = 0 + for c in f: + sum = sum + int(c) + + print 'Sum of digits in 100!:', sum -print 'Sum of digits in 100!:', sum \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/e021.py b/e021.py index 6f39938..17f9c5c 100644 --- a/e021.py +++ b/e021.py @@ -1,3 +1,13 @@ +"""Evaluate the sum of all amicable pairs under 10000. + +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. +""" + from e007 import is_prime from e012 import factor @@ -10,7 +20,7 @@ def proper_divisors(n): # Knock off the last factor, since it is equal to n return divisors[:-1] -if __name__ == '__main__': +def main(): MIN = 2 MAX = 10000 @@ -26,4 +36,6 @@ if __name__ == '__main__': amicable.append(i) amicable.append(s) i = i + 1 - print 'Sum of amicable numbers less than {0}: {1}'.format(MAX, sum(amicable)) \ No newline at end of file + print 'Sum of amicable numbers less than {0}: {1}'.format(MAX, sum(amicable)) +if __name__ == '__main__': + main() diff --git a/e022.py b/e022.py index 4dd78ef..cf63309 100644 --- a/e022.py +++ b/e022.py @@ -1,19 +1,31 @@ +"""What is the total of all the name scores in the file of first names? + +Using names.txt (p022/names.txt), 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? +""" + import csv -names = [] -reader = csv.reader(open('p022/names.txt'), delimiter=',', quotechar='"') -for row in reader: - names = names + row -names = sorted(names) -total = 0 +def main(): + names = [] + reader = csv.reader(open('p022/names.txt'), delimiter=',', quotechar='"') + for row in reader: + names = names + row + names = sorted(names) + total = 0 + + i = 1 + for name in names: + score = 0 + for c in name: + score = score + (ord(c) - 64) + score = i * score + total = total + score + i = i + 1 + + print 'Total:', total -i = 1 -for name in names: - score = 0 - for c in name: - score = score + (ord(c) - 64) - score = i * score - total = total + score - i = i + 1 - -print 'Total:', total \ No newline at end of file +if __name__ == '__main__': + main() diff --git a/e023.py b/e023.py index 3ea4ae4..717bbc4 100644 --- a/e023.py +++ b/e023.py @@ -1,20 +1,33 @@ +"""Find the sum of all the positive integers which cannot be written as the sum of two abundant numbers. + +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. +""" + from e021 import proper_divisors -abundant = [] -total = 1 +def main(): + abundant = [] + total = 1 + + i = 2 + while i < 28123: + s = sum(proper_divisors(i)) + if s > i: + abundant.append(i) + summed = False + for a in abundant: + if i - a in abundant: + summed = True + break + if not summed: + total = total + i + i = i + 1 + + print 'Total:', total -i = 2 -while i < 28123: - s = sum(proper_divisors(i)) - if s > i: - abundant.append(i) - summed = False - for a in abundant: - if i - a in abundant: - summed = True - break - if not summed: - total = total + i - i = i + 1 - -print 'Total:', total +if __name__ == '__main__': + main() diff --git a/e024.py b/e024.py index 3960f9d..8c0ae34 100644 --- a/e024.py +++ b/e024.py @@ -1,3 +1,11 @@ +"""What is the millionth lexicographic permutation of the digits 0, 1, 2, 3, 4, 5, 6, 7, 8 and 9? + +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? +""" + import math def lexicographic_permutation(list, position): @@ -17,7 +25,7 @@ def lexicographic_permutation(list, position): p.append(list.pop(index)) return p -if __name__ == '__main__': +def main(): print 'Testing permutations of 0..2:' list = [str(i) for i in [0, 1, 2]] for i in range(1, math.factorial(len(list)) + 1): @@ -27,3 +35,6 @@ if __name__ == '__main__': list = [str(i) for i in [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]] p = lexicographic_permutation(list, 1000000) print '1 millionth lexicographic permutation of 0..9:', ''.join(p) + +if __name__ == '__main__': + main() diff --git a/e025.py b/e025.py index b0dab1b..d03d207 100644 --- a/e025.py +++ b/e025.py @@ -1,3 +1,27 @@ +"""What is the first term in the Fibonacci sequence to contain 1000 digits? + +The Fibonacci sequence is defined by the recurrence relation: + Fn = Fn1 + Fn2, 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 first term in the Fibonacci sequence to contain 1000 digits? +""" + def fibonacci(n, limit=None): fibonacci = [0, 1] i = 2 @@ -9,6 +33,9 @@ def fibonacci(n, limit=None): i = i + 1 return (n, fibonacci[n]) -if __name__ == '__main__': +def main(): (term, value) = fibonacci(10**999, 10**999) print 'First Fibonacci term with at least 1000 digits is #{0}: {1}'.format(term, value) + +if __name__ == '__main__': + main() diff --git a/e028.py b/e028.py index ba3fb12..8454e3f 100644 --- a/e028.py +++ b/e028.py @@ -1,14 +1,32 @@ -n = 1 -total = 1 -size = 1 +"""What is the sum of both diagonals in a 1001 by 1001 spiral? -MAX_SIZE = 1001 +Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows: -while size <= MAX_SIZE: - for i in range(4): - n = n + (size - 1) - if n > 1: - total = total + n - size = size + 2 + [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] -print 'Total:', total +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? +""" + +def main(): + n = 1 + total = 1 + size = 1 + + MAX_SIZE = 1001 + + while size <= MAX_SIZE: + for i in range(4): + n = n + (size - 1) + if n > 1: + total = total + n + size = size + 2 + + print 'Total:', total + +if __name__ == '__main__': + main() diff --git a/e029.py b/e029.py index 999163a..8ac4919 100644 --- a/e029.py +++ b/e029.py @@ -1,10 +1,28 @@ +# -*- coding: utf-8 -*- +""""How many distinct terms are in the sequence generated by a**b for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100? + +Consider all integer combinations of a**b for 2 ≤ a ≤ 5 and 2 ≤ b ≤ 5: + 2**2=4, 2**3=8, 2**4=16, 2**5=32 + 3**2=9, 3**3=27, 3**4=81, 3**5=243 + 4**2=16, 4**3=64, 4**4=256, 4**5=1024 + 5**2=25, 5**3=125, 5**4=625, 5**5=3125 + +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 a**b for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100? +""" MAX = 100 -numbers = [] +def main(): + numbers = [] + + for i in range(2, MAX + 1): + for ii in range(2, MAX + 1): + n = i**ii + if n not in numbers: + numbers.append(n) + print len(numbers) -for i in range(2, MAX + 1): - for ii in range(2, MAX + 1): - n = i**ii - if n not in numbers: - numbers.append(n) -print len(numbers) +if __name__ == '__main__': + main() diff --git a/e030.py b/e030.py index f3fa3a6..28b5b2b 100644 --- a/e030.py +++ b/e030.py @@ -1,3 +1,16 @@ +"""Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. + +Surprisingly there are only three numbers that can be written as the sum of fourth powers of their digits: + 1634 = 1**4 + 6**4 + 3**4 + 4**4 + 8208 = 8**4 + 2**4 + 0**4 + 8**4 + 9474 = 9**4 + 4**4 + 7**4 + 4**4 + +As 1 = 14 is not a sum it is not included. +The sum of these numbers is 1634 + 8208 + 9474 = 19316. + +Find the sum of all the numbers that can be written as the sum of fifth powers of their digits. +""" + def power_sums(n): numbers = [] i = 9 @@ -10,7 +23,11 @@ def power_sums(n): numbers.append(i) return numbers -p = power_sums(4) -print 'power_sums(4)', p, sum(p) -p = power_sums(5) -print 'power_sums(5)', p, sum(p) +def main(): + p = power_sums(4) + print 'power_sums(4)', p, sum(p) + p = power_sums(5) + print 'power_sums(5)', p, sum(p) + +if __name__ == '__main__': + main() diff --git a/e034.py b/e034.py index 9916fc5..f99319c 100644 --- a/e034.py +++ b/e034.py @@ -1,3 +1,11 @@ +"""Find the sum of all numbers which are equal to the sum of the factorial of their digits. + +145 is a curious number, as 1! + 4! + 5! = 1 + 24 + 120 = 145. +Find the sum of all numbers which are equal to the sum of the factorial of their digits. + +Note: as 1! = 1 and 2! = 2 are not sums they are not included. +""" + import math def sum_factorial(n): @@ -9,7 +17,7 @@ def sum_factorial(n): MAX = 100000 -if __name__ == '__main__': +def main(): total = 0 i = 2 while i <= MAX: @@ -18,3 +26,6 @@ if __name__ == '__main__': print i total = total + i print 'Total:', total + +if __name__ == '__main__': + main() diff --git a/e035.py b/e035.py index 76bdde5..4bfb312 100644 --- a/e035.py +++ b/e035.py @@ -1,3 +1,11 @@ +"""How many circular primes are there below one million? + +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? +""" + from e007 import primes class NotCircular(Exception): @@ -19,7 +27,7 @@ def cyclic_rotation(n): for i in xrange(len(s)): yield int(s[i:] + s[:i]) -if __name__ == '__main__': +def main(): MAX = 1000000 circular_primes = [] print 'Generating primes for p < {0}...'.format(MAX) @@ -40,3 +48,6 @@ if __name__ == '__main__': pass # Clear all permutations from the list? print 'Circular Primes ({0}): {1}'.format(len(circular_primes), circular_primes) + +if __name__ == '__main__': + main() diff --git a/e036.py b/e036.py index 72855eb..7aeb309 100644 --- a/e036.py +++ b/e036.py @@ -1,9 +1,17 @@ +"""Find the sum of all numbers less than one million, which are palindromic in base 10 and base 2. + +The decimal number, 585 = 10010010012 (binary), is palindromic in both bases. +Find the sum of all numbers, less than one million, which are palindromic in base 10 and base 2. + +(Please note that the palindromic number, in either base, may not include leading zeros.) +""" + MAX = 1000000 def binary(n): return '{0:b}'.format(n) -if __name__ == '__main__': +def main(): total = 0 i = 0 while i < MAX: @@ -17,3 +25,6 @@ if __name__ == '__main__': print n, b total = total + i print 'Total:', total + +if __name__ == '__main__': + main() diff --git a/e048.py b/e048.py index 6f19eaa..ee2b41f 100644 --- a/e048.py +++ b/e048.py @@ -1,3 +1,10 @@ +"""Find the last ten digits of 1**1 + 2**2 + ... + 1000**1000. + +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. +""" + def powerseries(n): i = 1 total = 0 @@ -6,6 +13,9 @@ def powerseries(n): i = i + 1 return total -if __name__ == '__main__': +def main(): val = str(powerseries(1000)) print 'Last 10:', val[-10:] + +if __name__ == '__main__': + main() diff --git a/e054.py b/e054.py index 209428e..301f733 100644 --- a/e054.py +++ b/e054.py @@ -1,6 +1,49 @@ +"""How many hands did player one win in the game of poker? + +In the card game poker, a hand consists of five cards and are ranked, from lowest to highest, in the following way: + High Card: Highest value card. + One Pair: Two cards of the same value. + Two Pairs: Two different pairs. + Three of a Kind: Three cards of the same value. + Straight: All cards are consecutive values. + Flush: All cards of the same suit. + Full House: Three of a kind and a pair. + Four of a Kind: Four cards of the same value. + Straight Flush: All cards are consecutive values of same suit. + Royal Flush: Ten, Jack, Queen, King, Ace, in same suit. + +The cards are valued in the order: + 2, 3, 4, 5, 6, 7, 8, 9, 10, Jack, Queen, King, Ace. + +If two players have the same ranked hands then the rank made up of the highest value wins; for example, a pair of eights beats a pair of fives (see example 1 below). But if two ranks tie, for example, both players have a pair of queens, then highest cards in each hand are compared (see example 4 below); if the highest cards tie then the next highest cards are compared, and so on. + +Consider the following five hands dealt to two players: + + Hand Player 1 Player 2 Winner + 1 5H 5C 6S 7S KD 2C 3S 8S 8D TD Player 2 + Pair of Fives Pair of Eights + + 2 5D 8C 9S JS AC 2C 5C 7D 8S QH + Highest card Ace Highest Card Queen Player 1 + 3 2D 9C AS AH AC 3D 6D 7D TD QD + Three Aces Flush with Diamonds Player 2 + + 4 4D 6S 9H QH QC 3D 6D 7H QD QS Player 1 + Pair of Queens Pair of Queens + Highest card Nine Highest card Seven + + 5 2H 2D 4C 4D 4S 3C 3D 3S 9S 9D Player 1 + Full House Full House + With Three Fours With Three Threes + +The file, poker.txt, contains one-thousand random hands dealt to two players. Each line of the file contains ten cards (separated by a single space): the first five are Player 1's cards and the last five are Player 2's cards. You can assume that all hands are valid (no invalid characters or repeated cards), each player's hand is in no specific order, and in each hand there is a clear winner. + +How many hands does Player 1 win? +""" + from p054 import poker -if __name__ == '__main__': +def main(): wins = 0 counter = 0 with open('p054/poker.txt', 'r') as f: @@ -26,3 +69,6 @@ if __name__ == '__main__': one, two) print "Player one won {0} hands".format(wins) + +if __name__ == '__main__': + main() diff --git a/e067.py b/e067.py index 0b8ff95..8af99af 100644 --- a/e067.py +++ b/e067.py @@ -1,13 +1,34 @@ +"""Using an efficient algorithm find the maximal sum in the triangle? + +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 (p067/triangle.txt), a 15K text file containing a triangle with one-hundred rows. + +NOTE: This is a much more difficult version of Problem 18. It is not possible to try every route to solve this problem, as there are 299 altogether! If you could check one trillion (10**12) routes every second it would take over twenty billion years to check them all. There is an efficient algorithm to solve it. ;o) +""" + from e018 import Triangle -vertex_data = [] -with open('p067/triangle.txt', 'r') as f: - while True: - line = f.readline() - if not line: - break - vertex_data = vertex_data + [int(v) for v in line.split(' ')] -t = Triangle(vertex_data) -t.find_path() -path = t.get_path() -print 'Path', [v.value for v in path] -print 'Sum', sum([v.value for v in path]) \ No newline at end of file + +def main(): + vertex_data = [] + with open('p067/triangle.txt', 'r') as f: + while True: + line = f.readline() + if not line: + break + vertex_data = vertex_data + [int(v) for v in line.split(' ')] + t = Triangle(vertex_data) + t.find_path() + path = t.get_path() + print 'Path', [v.value for v in path] + print 'Sum', sum([v.value for v in path]) + +if __name__ == '__main__': + main() diff --git a/p015/p_015.gif b/p015/p_015.gif new file mode 100644 index 0000000..2c07c68 Binary files /dev/null and b/p015/p_015.gif differ