diff --git a/C/p003.c b/C/p003.c index ccc05a7..c5de8da 100644 --- a/C/p003.c +++ b/C/p003.c @@ -4,7 +4,6 @@ #include #include -#include #include #include "projecteuler.h" diff --git a/C/p011.c b/C/p011.c index 308f33e..90a9c9d 100644 --- a/C/p011.c +++ b/C/p011.c @@ -1,4 +1,4 @@ -/* n the 20×20 grid below, four numbers along a diagonal line have been marked in red. +/* In the 20×20 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 diff --git a/C/p020.c b/C/p020.c index 3524a23..58f198a 100644 --- a/C/p020.c +++ b/C/p020.c @@ -33,7 +33,7 @@ int main(int argc, char **argv) clock_gettime(CLOCK_MONOTONIC, &end); - elapsed=(end.tv_sec-start.tv_sec)+(double)(end.tv_nsec-start.tv_nsec)/1000000000; + elapsed = (end.tv_sec - start.tv_sec) + (double)(end.tv_nsec - start.tv_nsec) / 1000000000; printf("Project Euler, Problem 20\n"); gmp_printf("Answer: %Zd\n", sum); diff --git a/C/p021.c b/C/p021.c index 1f142be..5fe230a 100644 --- a/C/p021.c +++ b/C/p021.c @@ -3,8 +3,8 @@ * * 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.*/ + * + * Evaluate the sum of all the amicable numbers under 10000.*/ #include #include diff --git a/Python/p001.py b/Python/p001.py index 12d2813..9223db3 100644 --- a/Python/p001.py +++ b/Python/p001.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer def main(): @@ -7,6 +11,8 @@ def main(): sum_ = 0 +# Simple brute-force approach: try every number between 3 and 999, +# check if it's a multiple of 3 or 5, if yes add it to the total. for i in range(3, 1000): if i % 3 == 0 or i % 5 == 0: sum_ += i diff --git a/Python/p002.py b/Python/p002.py index dafd087..e16c4a0 100644 --- a/Python/p002.py +++ b/Python/p002.py @@ -1,17 +1,27 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer def main(): start = default_timer() + N = 4000000 + fib1 = 1 fib2 = 2 fibn = fib1 + fib2 sum_ = 2 - while fibn < 4000000: +# Simple brute-force approach: generate every value in the Fibonacci +# sequence smaller than 4 million and if it's even add it to the total. + while fibn < N: if fibn % 2 == 0: sum_ = sum_ + fibn diff --git a/Python/p003.py b/Python/p003.py index b7adcbf..cb395c6 100644 --- a/Python/p003.py +++ b/Python/p003.py @@ -1,24 +1,39 @@ #!/usr/bin/python3 +# The prime factors of 13195 are 5, 7, 13 and 29. +# +# What is the largest prime factor of the number 600851475143? + from math import floor, sqrt from timeit import default_timer from projecteuler import is_prime +# Recursive approach: if num is prime, return num, otherwise +# recursively look for the largest prime factor of num divided +# by its prime factors until only the largest remains. def max_prime_factor(num): +# Use function defined in projecteuler.py to check if a number is prime. if is_prime(num): return num +# If num is even, find the largest prime factor of num/2. if num % 2 == 0: return max_prime_factor(num // 2) else: - limit = floor(sqrt(num)) + 1 + i = 3 - for i in range(3, limit, 2): +# If num is divisible by i and i is prime, find largest +# prime factor of num/i. + while 1: if num % i == 0: if is_prime(i): - return max_prime_factor(num // i) + return max_prime_factor(num//i) + i = i + 2 + +# Should never get here + return -1 def main(): start = default_timer() diff --git a/Python/p004.py b/Python/p004.py index eb7d8d6..891064c 100644 --- a/Python/p004.py +++ b/Python/p004.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer from projecteuler import is_palindrome @@ -8,9 +12,13 @@ def main(): max_ = 0 +# Using a brute-force approach: generate every product of 3-digit numbers +# and check if it's palindrome. If the product found is greater than the +# current maximum, save the current product. for i in range(999, 99, -1): for j in range(i, 99, -1): num = i * j +# Use the function defined in projecteuler.py to check if a number is palindrome. if num > max_ and is_palindrome(num, 10): max_ = num diff --git a/Python/p005.py b/Python/p005.py index c6df296..460dcf4 100644 --- a/Python/p005.py +++ b/Python/p005.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# 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? + from timeit import default_timer from projecteuler import lcmm @@ -9,6 +13,7 @@ def main(): values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20) +# Function define in projecteuler.py to find the least common multiple of multiple numbers. res = lcmm(values, 20) end = default_timer() diff --git a/Python/p006.py b/Python/p006.py index 4c8e17b..e15a697 100644 --- a/Python/p006.py +++ b/Python/p006.py @@ -1,12 +1,26 @@ #!/usr/bin/python3 +# 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 = 55^2 = 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. + from timeit import default_timer + def main(): start = default_timer() sum_squares = 0 square_sum = 0 +# Straightforward brute-force approach. for i in range(1, 101): sum_squares = sum_squares + i * i square_sum = square_sum + i diff --git a/Python/p007.py b/Python/p007.py index f5b4020..9d65252 100644 --- a/Python/p007.py +++ b/Python/p007.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# 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? + from timeit import default_timer from projecteuler import is_prime @@ -9,9 +13,12 @@ def main(): count = 1 n = 1 +# Brute force approach: start with count=1 and check every odd number +# (2 is the only even prime), if it's prime increment count, until the +# target prime is reached. while count != 10001: n = n + 2 - +# Use the function in projecteuler.py to check if a number is prime. if is_prime(n): count = count + 1 diff --git a/Python/p008.py b/Python/p008.py index 08e5cf2..8b8b090 100644 --- a/Python/p008.py +++ b/Python/p008.py @@ -1,5 +1,30 @@ #!/usr/bin/python3 +# The four adjacent digits in the 1000-digit number that have the greatest product are 9 × 9 × 8 × 9 = 5832. +# +# 73167176531330624919225119674426574742355349194934 +# 96983520312774506326239578318016984801869478851843 +# 85861560789112949495459501737958331952853208805511 +# 12540698747158523863050715693290963295227443043557 +# 66896648950445244523161731856403098711121722383113 +# 62229893423380308135336276614282806444486645238749 +# 30358907296290491560440772390713810515859307960866 +# 70172427121883998797908792274921901699720888093776 +# 65727333001053367881220235421809751254540594752243 +# 52584907711670556013604839586446706324415722155397 +# 53697817977846174064955149290862569321978468622482 +# 83972241375657056057490261407972968652414535100474 +# 82166370484403199890008895243450658541227588666881 +# 16427171479924442928230863465674813919123162824586 +# 17866458359124566529476545682848912883142607690042 +# 24219022671055626321111109370544217506941658960408 +# 07198403850962455444362981230987879927244284909188 +# 84580156166097919133875499200524063689912560717606 +# 05886116467109405077541002256983155200055935729725 +# 71636269561882670428252483600823257530420752963450 +# +# Find the thirteen adjacent digits in the 1000-digit number that have the greatest product. What is the value of this product? + from timeit import default_timer def main(): @@ -25,10 +50,12 @@ def main(): '05886116467109405077541002256983155200055935729725' +\ '71636269561882670428252483600823257530420752963450' +# Transform the string into a list of integers number = list(map(int, number)) max_ = 0 +# Calculate all the 13-digit products, and save the maximum for i in range(1000-13): curr = number[i:i+13] prod = 1 diff --git a/Python/p009.py b/Python/p009.py index a7380d3..64125c9 100644 --- a/Python/p009.py +++ b/Python/p009.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer def main(): @@ -9,6 +19,8 @@ def main(): m = 2 +# Brute force approach: generate all the Pythagorean triplets using +# Euclid's formula, until the one where a+b+c=1000 is found. while not found: for n in range(1, m): a = m * m - n * n diff --git a/Python/p010.py b/Python/p010.py index 61ef817..08fe9bb 100644 --- a/Python/p010.py +++ b/Python/p010.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. +# +# Find the sum of all the primes below two million. + from timeit import default_timer from projecteuler import sieve @@ -8,9 +12,12 @@ def main(): N = 2000000 +# Use the function in projecteuler.py implementing the +# Sieve of Eratosthenes algorithm to generate primes. primes = sieve(N) sum_ = 0 +# Sum all the primes for i in range(N): if primes[i] == 1: sum_ = sum_ + i diff --git a/Python/p011.py b/Python/p011.py index bc2868c..285efee 100644 --- a/Python/p011.py +++ b/Python/p011.py @@ -1,5 +1,32 @@ #!/usr/bin/python3 +# In the 20×20 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 the same direction (up, down, left, right, or diagonally) in the 20×20 grid? + from timeit import default_timer def main(): @@ -28,11 +55,14 @@ def main(): max_ = 0 +# Brute-force approach: for each number in the grid, try products with its three +# adjacent numbers in every direction (horizontal, vertical and the two diagonals). +# If the product is larger than the current maximum, save it. for i in range(17): for j in range(17): +# Horizontal direction. prod = 1 k = j - while k < j + 4: prod = prod * grid[i][k] k = k + 1 @@ -40,9 +70,9 @@ def main(): if prod > max_: max_ = prod +# Vertical direction. prod = 1 k = i - while k < i + 4: prod = prod * grid[k][j] k = k + 1 @@ -50,6 +80,7 @@ def main(): if prod > max_: max_ = prod +# Diagonal direction, from top left to bottom right. prod = 1 k = i w = j @@ -62,8 +93,10 @@ def main(): if prod > max_: max_ = prod +# The last diagonal is handled separately for i in range(17): for j in range(3, 20): +# Diagonal direction, from top right to bottom left. prod = 1 k = i w = j diff --git a/Python/p012.py b/Python/p012.py index c656802..24787d9 100644 --- a/Python/p012.py +++ b/Python/p012.py @@ -1,5 +1,24 @@ #!/usr/bin/python3 +# 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 timeit import default_timer from projecteuler import count_divisors @@ -10,10 +29,12 @@ def main(): triang = 0 finished = 0 +# Generate all triangle numbers until the first one with more than 500 divisors is found. while not finished: i = i + 1 triang = triang + i +# Use the function implemented in projecteuler.py to count divisors of a number. if count_divisors(triang) > 500: finished = 1 diff --git a/Python/p013.py b/Python/p013.py index bd7f183..6488332 100644 --- a/Python/p013.py +++ b/Python/p013.py @@ -1,5 +1,108 @@ #!/usr/bin/python3 +# Work out the first ten digits of the sum of the following one-hundred 50-digit numbers. +# +# 37107287533902102798797998220837590246510135740250 +# 46376937677490009712648124896970078050417018260538 +# 74324986199524741059474233309513058123726617309629 +# 91942213363574161572522430563301811072406154908250 +# 23067588207539346171171980310421047513778063246676 +# 89261670696623633820136378418383684178734361726757 +# 28112879812849979408065481931592621691275889832738 +# 44274228917432520321923589422876796487670272189318 +# 47451445736001306439091167216856844588711603153276 +# 70386486105843025439939619828917593665686757934951 +# 62176457141856560629502157223196586755079324193331 +# 64906352462741904929101432445813822663347944758178 +# 92575867718337217661963751590579239728245598838407 +# 58203565325359399008402633568948830189458628227828 +# 80181199384826282014278194139940567587151170094390 +# 35398664372827112653829987240784473053190104293586 +# 86515506006295864861532075273371959191420517255829 +# 71693888707715466499115593487603532921714970056938 +# 54370070576826684624621495650076471787294438377604 +# 53282654108756828443191190634694037855217779295145 +# 36123272525000296071075082563815656710885258350721 +# 45876576172410976447339110607218265236877223636045 +# 17423706905851860660448207621209813287860733969412 +# 81142660418086830619328460811191061556940512689692 +# 51934325451728388641918047049293215058642563049483 +# 62467221648435076201727918039944693004732956340691 +# 15732444386908125794514089057706229429197107928209 +# 55037687525678773091862540744969844508330393682126 +# 18336384825330154686196124348767681297534375946515 +# 80386287592878490201521685554828717201219257766954 +# 78182833757993103614740356856449095527097864797581 +# 16726320100436897842553539920931837441497806860984 +# 48403098129077791799088218795327364475675590848030 +# 87086987551392711854517078544161852424320693150332 +# 59959406895756536782107074926966537676326235447210 +# 69793950679652694742597709739166693763042633987085 +# 41052684708299085211399427365734116182760315001271 +# 65378607361501080857009149939512557028198746004375 +# 35829035317434717326932123578154982629742552737307 +# 94953759765105305946966067683156574377167401875275 +# 88902802571733229619176668713819931811048770190271 +# 25267680276078003013678680992525463401061632866526 +# 36270218540497705585629946580636237993140746255962 +# 24074486908231174977792365466257246923322810917141 +# 91430288197103288597806669760892938638285025333403 +# 34413065578016127815921815005561868836468420090470 +# 23053081172816430487623791969842487255036638784583 +# 11487696932154902810424020138335124462181441773470 +# 63783299490636259666498587618221225225512486764533 +# 67720186971698544312419572409913959008952310058822 +# 95548255300263520781532296796249481641953868218774 +# 76085327132285723110424803456124867697064507995236 +# 37774242535411291684276865538926205024910326572967 +# 23701913275725675285653248258265463092207058596522 +# 29798860272258331913126375147341994889534765745501 +# 18495701454879288984856827726077713721403798879715 +# 38298203783031473527721580348144513491373226651381 +# 34829543829199918180278916522431027392251122869539 +# 40957953066405232632538044100059654939159879593635 +# 29746152185502371307642255121183693803580388584903 +# 41698116222072977186158236678424689157993532961922 +# 62467957194401269043877107275048102390895523597457 +# 23189706772547915061505504953922979530901129967519 +# 86188088225875314529584099251203829009407770775672 +# 11306739708304724483816533873502340845647058077308 +# 82959174767140363198008187129011875491310547126581 +# 97623331044818386269515456334926366572897563400500 +# 42846280183517070527831839425882145521227251250327 +# 55121603546981200581762165212827652751691296897789 +# 32238195734329339946437501907836945765883352399886 +# 75506164965184775180738168837861091527357929701337 +# 62177842752192623401942399639168044983993173312731 +# 32924185707147349566916674687634660915035914677504 +# 99518671430235219628894890102423325116913619626622 +# 73267460800591547471830798392868535206946944540724 +# 76841822524674417161514036427982273348055556214818 +# 97142617910342598647204516893989422179826088076852 +# 87783646182799346313767754307809363333018982642090 +# 10848802521674670883215120185883543223812876952786 +# 71329612474782464538636993009049310363619763878039 +# 62184073572399794223406235393808339651327408011116 +# 66627891981488087797941876876144230030984490851411 +# 60661826293682836764744779239180335110989069790714 +# 85786944089552990653640447425576083659976645795096 +# 66024396409905389607120198219976047599490197230297 +# 64913982680032973156037120041377903785566085089252 +# 16730939319872750275468906903707539413042652315011 +# 94809377245048795150954100921645863754710598436791 +# 78639167021187492431995700641917969777599028300699 +# 15368713711936614952811305876380278410754449733078 +# 40789923115535562561142322423255033685442488917353 +# 44889911501440648020369068063960672322193204149535 +# 41503128880339536053299340368006977710650566631954 +# 81234880673210146739058568557934581403627822703280 +# 82616570773948327592232845941706525094512325230608 +# 22918802058777319719839450180888072429661980811197 +# 77158542502016545090413245809786882778948721859617 +# 72107838435069186155435662884062257473692284509516 +# 20849603980134001723930671666823555245252804609722 +# 53503534226472524250874054075591789781264330331690 + import numpy as np from timeit import default_timer @@ -108,6 +211,7 @@ def main(): 20849603980134001723930671666823555245252804609722, 53503534226472524250874054075591789781264330331690] +# Convert the list of numbers in a numpy array and calculate the sum numbers = np.array(numbers) sum_ = str(numbers.sum()) diff --git a/Python/p014.py b/Python/p014.py index c533fdf..0377079 100644 --- a/Python/p014.py +++ b/Python/p014.py @@ -1,15 +1,39 @@ #!/usr/bin/python3 + +# 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. + from numpy import zeros from timeit import default_timer -collatz_found = zeros(1000000, dtype=int) +N = 1000000 +collatz_found = zeros(N, dtype=int) +# Recursive function to calculate the Collatz sequence for n. +# If n is even, Collatz(n)=1+Collatz(n/2), if n is odd +# Collatz(n)=1+Collatz(3*n+1). def collatz_length(n): + if n == 1: return 1 - if n < 1000000 and collatz_found[n]: +# If Collatz(n) has been previously calculated, +# just return the value. + if n < N and collatz_found[n]: return collatz_found[n] if n % 2 == 0: @@ -23,7 +47,9 @@ def main(): max_l = 0 max_ = 0 - for i in range(1, 1000000): +# For each number from 1 to 1000000, find the length of the sequence +# and save its value, so that it can be used for the next numbers. + for i in range(1, N): count = collatz_length(i) collatz_found[i] = count diff --git a/Python/p015.py b/Python/p015.py index 27be29f..30555be 100644 --- a/Python/p015.py +++ b/Python/p015.py @@ -1,5 +1,8 @@ #!/usr/bin/python3 +# 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? + from math import factorial from timeit import default_timer @@ -7,6 +10,10 @@ from timeit import default_timer def main(): start = default_timer() +# Using a combinatorial solution: in a 20x20 grid there will always be +# 20 movements to the right and 20 movements down, that can be represented +# as a string of Rs and Ds. The number of routes is the number of combinations. +# This is obtained calculating n!/(k!*(n-k)!), where n=40 and k=20. count = factorial(40) tmp = factorial(20) tmp = tmp * tmp diff --git a/Python/p016.py b/Python/p016.py index 8b387fe..a2556c5 100644 --- a/Python/p016.py +++ b/Python/p016.py @@ -1,10 +1,16 @@ #!/usr/bin/python3 +# 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? + from timeit import default_timer def main(): start = default_timer() +# Simply calculate 2^1000, convert the result to string and calculate +# the sum of the digits res = str(2 ** 1000) sum_ = 0 diff --git a/Python/p017.py b/Python/p017.py index becd977..f458b12 100644 --- a/Python/p017.py +++ b/Python/p017.py @@ -1,32 +1,59 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer def main(): start = default_timer() +# First list contains number of letters for numbers from 1 to 19, +# the second letters for "twenty", "thirty", ..., "ninety", +# the third letters for "one hundred and", "two hundred and", ..., "nine hundre and", +# the last one-element one the number of letters of 1000 n_letters = [[3, 3, 5, 4, 4, 3, 5, 5, 4, 3, 6, 6, 8, 8, 7, 7, 9, 8, 8],\ - [60, 60, 50, 50, 50, 70, 60, 60],\ - [1300, 1300, 1500, 1400, 1400, 1300, 1500, 1500, 1400],\ + [6, 6, 5, 5, 5, 7, 6, 6],\ + [13, 13, 15, 14, 14, 13, 15, 15, 14],\ [11]] sum_ = 0 +# Sum the letters of the first 19 numbers. for i in range(19): sum_ = sum_ + n_letters[0][i] +# Add the letters of the numbers from 20 to 99. for i in range(8): +# "Twenty", "thirty", ... "ninety" are used ten times each +# (e.g. "twenty", "twenty one", "twenty two", ..., "twenty nine"). + n_letters[1][i] = n_letters[1][i] * 10 + +# Add "one", "two", ..., "nine". for j in range(9): n_letters[1][i] = n_letters[1][i] + n_letters[0][j] sum_ = sum_ + n_letters[1][i] +# Add the letters of the numbers from 100 to 999. for i in range(9): +# "One hundred and", "two hundred and",... are used 100 times each. + n_letters[2][i] = n_letters[2][i] * 100 + +# Add "one" to "nineteen". for j in range(19): n_letters[2][i] = n_letters[2][i] + n_letters[0][j] +# Add "twenty" to "ninety nine", previously calculated. for j in range(8): n_letters[2][i] = n_letters[2][i] + n_letters[1][j] +# "One hundred", "two hundred", ... don't have the "and", so remove +# three letters for each of them. sum_ = sum_ + n_letters[2][i] - 3 +# Add "one thousand". sum_ = sum_ + n_letters[3][0] end = default_timer() diff --git a/Python/p018.py b/Python/p018.py index d66de38..c0d325f 100644 --- a/Python/p018.py +++ b/Python/p018.py @@ -1,5 +1,35 @@ #!/usr/bin/python3 +# 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 timeit import default_timer from projecteuler import find_max_path @@ -24,6 +54,7 @@ def main(): for i in range(l): triang[i] = list(map(int, triang[i])) +# Use function implemented in projecteuler.c to find the maximum path. max_ = find_max_path(triang, 15) end = default_timer() diff --git a/Python/p019.py b/Python/p019.py index 1cb1577..793ac71 100644 --- a/Python/p019.py +++ b/Python/p019.py @@ -1,5 +1,18 @@ #!/usr/bin/python3 +# 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)? + import datetime from timeit import default_timer @@ -9,6 +22,7 @@ def main(): count = 0 +# Use the datetime library to find out which first day of the month is a Sunday for year in range(1901, 2001): for month in range(1, 13): if datetime.datetime(year, month, 1).weekday() == 6: diff --git a/Python/p020.py b/Python/p020.py index ab52d1f..64201d2 100644 --- a/Python/p020.py +++ b/Python/p020.py @@ -1,5 +1,12 @@ #!/usr/bin/python3 +# 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! + from math import factorial from timeit import default_timer @@ -7,6 +14,7 @@ from timeit import default_timer def main(): start = default_timer() +# Calculate the factorial, convert the result to string and sum the digits. n = str(factorial(100)) sum_ = 0 diff --git a/Python/p021.py b/Python/p021.py index 0ea5b61..8726213 100644 --- a/Python/p021.py +++ b/Python/p021.py @@ -1,21 +1,17 @@ #!/usr/bin/python3 +# 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 math import floor, sqrt from timeit import default_timer - -def sum_of_divisors(n): - limit = floor(sqrt(n)) + 1 - - sum_ = 1 - - for i in range(2, limit): - if n % i == 0: - sum_ = sum_ + i - if n != i * i: - sum_ = sum_ + n // i - - return sum_ +from projecteuler import sum_of_divisors def main(): start = default_timer() @@ -23,7 +19,11 @@ def main(): sum_ = 0 for i in range(2, 10000): +# Calculate the sum of proper divisors with the function +# implemented in projecteuler.py. n = sum_of_divisors(i) +# If i!=n and the sum of proper divisors of n=i, +# sum the pair of numbers and add it to the total. if i != n and sum_of_divisors(n) == i: sum_ = sum_ + i + n diff --git a/Python/p022.py b/Python/p022.py index 2897fed..4709576 100644 --- a/Python/p022.py +++ b/Python/p022.py @@ -1,5 +1,13 @@ #!/usr/bin/python3 +# Using 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? + from timeit import default_timer def main(): @@ -17,6 +25,7 @@ def main(): sum_ = 0 i = 1 +# Calculate the score of each name an multiply by its position. for name in names: l = len(name) score = 0 diff --git a/Python/p023.py b/Python/p023.py index f731eef..0d7bd54 100644 --- a/Python/p023.py +++ b/Python/p023.py @@ -1,31 +1,39 @@ #!/usr/bin/python3 +# 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 math import floor, sqrt from timeit import default_timer +from projecteuler import sum_of_divisors def is_abundant(n): - limit = floor(sqrt(n)) + 1 - sum_ = 1 - - for i in range(2, limit): - if n % i == 0: - sum_ = sum_ + i - if n != i * i: - sum_ = sum_ + n // i - - return sum_ > n + return sum_of_divisors(n) > n def main(): start = default_timer() ab_nums = [False] * 28124 +# Find all abundant numbers smaller than 28123. for i in range(12, 28124): ab_nums[i] = is_abundant(i) sums = [False] * 28124 +# For every abundant number, sum every other abundant number greater +# than itself, until the sum exceeds 28123. Record that the resulting +# number is the sum of two abundant numbers. for i in range(1, 28123): if ab_nums[i]: for j in range(i, 28123): @@ -36,6 +44,7 @@ def main(): sum_ = 0 +# Sum every number that was not found as a sum of two abundant numbers. for i in range(1, 28124): if not sums[i]: sum_ = sum_ + i diff --git a/Python/p024.py b/Python/p024.py index 58f90b1..2674bb1 100644 --- a/Python/p024.py +++ b/Python/p024.py @@ -1,5 +1,12 @@ #!/usr/bin/python3 +# 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? + from itertools import permutations from timeit import default_timer @@ -7,6 +14,7 @@ from timeit import default_timer def main(): start = default_timer() +# Generate all the permutations in lexicographic order and get the millionth one. perm = list(permutations('0123456789')) res = int(''.join(map(str, perm[999999]))) diff --git a/Python/p025.py b/Python/p025.py index 3356676..12174f8 100644 --- a/Python/p025.py +++ b/Python/p025.py @@ -1,5 +1,26 @@ #!/usr/bin/python3 +# 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? + from timeit import default_timer def main(): @@ -11,6 +32,7 @@ def main(): i = 3 +# Calculate the Fibonacci numbers until one with 1000 digits is found. while len(str(fibn)) < 1000: fib1 = fib2 fib2 = fibn diff --git a/Python/projecteuler.py b/Python/projecteuler.py index 0c36d57..67c83ee 100644 --- a/Python/projecteuler.py +++ b/Python/projecteuler.py @@ -6,17 +6,26 @@ from numpy import ndarray, zeros def is_prime(num): if num < 4: +# If num is 2 or 3 then it's prime. return num == 2 or num == 3 +# If num is divisible by 2 or 3 then it's not prime. if num % 2 == 0 or num % 3 == 0: return False - +# Any number can have only one prime factor greater than its +# square root. If we reach the square root and we haven't found +# any smaller prime factors, then the number is prime. limit = floor(sqrt(num)) + 1 +# Every prime other than 2 and 3 is in the form 6k+1 or 6k-1. +# If I check all those value no prime factors of the number +# will be missed. If a factor is found, the number is not prime +# and the function returns 0. for i in range(5, limit, 6): if num % i == 0 or num % (i + 2) == 0: return False +# If no factor is found up to the square root of num, num is prime. return True def is_palindrome(num, base): @@ -24,44 +33,64 @@ def is_palindrome(num, base): tmp = num +# Start with reverse=0, get the rightmost digit of the number using +# modulo operation (num modulo base), add it to reverse. Remove the +# rightmost digit from num dividing num by the base, shift the reverse left +# multiplying by the base, repeat until all digits have been inserted +# in reverse order. while tmp > 0: reverse = reverse * base reverse = reverse + tmp % base tmp = tmp // base +# If the reversed number is equal to the original one, then it's palindrome. if num == reverse: return True return False - +# Least common multiple algorithm using the greatest common divisor. def lcm(a, b): return a * b // gcd(a, b) +# Recursive function to calculate the least common multiple of more than 2 numbers. def lcmm(values, n): +# If there are only two numbers, use the lcm function to calculate the lcm. if n == 2: return lcm(values[0], values[1]) value = values[0] - for i in range(1, n): - return lcm(value, lcmm(values[i:], n-1)) +# Recursively calculate lcm(a, b, c, ..., n) = lcm(a, lcm(b, c, ..., n)). + return lcm(value, lcmm(values[1:], n-1)) +# Function implementing the Sieve or Eratosthenes to generate +# primes up to a certain number. def sieve(n): primes = ndarray((n,), int) +# 0 and 1 are not prime, 2 and 3 are prime. primes[0] = 0 primes[1] = 0 primes[2] = 1 primes[3] = 1 +# Cross out (set to 0) all even numbers and set the odd numbers to 1 (possible prime). for i in range(4, n -1, 2): primes[i] = 0 primes[i+1] = 1 +# If i is prime, all multiples of i smaller than i*i have already been crossed out. +# if i=sqrt(n), all multiples of i up to n (the target) have been crossed out. So +# there is no need check i>sqrt(n). limit = floor(sqrt(n)) for i in range(3, limit, 2): +# Find the next number not crossed out, which is prime. if primes[i] == 1: +# Cross out all multiples of i, starting with i*i because any smaller multiple +# of i has a smaller prime factor and has already been crossed out. Also, since +# i is odd, i*i+i is even and has already been crossed out, so multiples are +# crossed out with steps of 2*i. for j in range(i * i, n, 2 * i): primes[j] = 0 @@ -69,6 +98,10 @@ def sieve(n): def count_divisors(n): count = 0 +# For every divisor below the square root of n, there is a corresponding one +# above the square root, so it's sufficient to check up to the square root of n +# and count every divisor twice. If n is a perfect square, the last divisor is +# wrongly counted twice and must be corrected. limit = floor(sqrt(n)) for i in range(1, limit): @@ -81,7 +114,11 @@ def count_divisors(n): return count def find_max_path(triang, n): +# Start from the second to last row and go up. for i in range(n-2, -1, -1): +# For each element in the row, check the two adjacent elements +# in the row below and sum the larger one to it. At the end, +# the element at the top will contain the value of the maximum path. for j in range(0, i+1): if triang[i+1][j] > triang[i+1][j+1]: triang[i][j] = triang[i][j] + triang[i+1][j] @@ -90,6 +127,26 @@ def find_max_path(triang, n): return triang[0][0] +def sum_of_divisors(n): +# For each divisor of n smaller than the square root of n, +# there is another one larger than the square root. If i is +# a divisor of n, so is n/i. Checking divisors i up to square +# root of n and adding both i and n/i is sufficient to sum +# all divisors. + limit = floor(sqrt(n)) + 1 + + sum_ = 1 + + for i in range(2, limit): + if n % i == 0: + sum_ = sum_ + i +# If n is a perfect square, i=limit is a divisor and +# has to be counted only once. + if n != i * i: + sum_ = sum_ + n // i + + return sum_ + def is_pandigital(value, n): i = 0 digits = zeros(n + 1, int) @@ -116,6 +173,8 @@ def is_pandigital(value, n): return True def is_pentagonal(n): +# A number n is pentagonal if p=(sqrt(24n+1)+1)/6 is an integer. +# In this case, n is the pth pentagonal number. i = (sqrt(24*n+1) + 1) / 6 return i.is_integer()