Add comments

Added comments to the python code for the first 25 problems
This commit is contained in:
daniele 2019-09-26 13:41:22 +02:00
parent ecdbadba7e
commit dfb13c083b
Signed by: fuxino
GPG Key ID: 6FE25B4A3EE16FDA
30 changed files with 538 additions and 44 deletions

View File

@ -4,7 +4,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h>
#include <time.h> #include <time.h>
#include "projecteuler.h" #include "projecteuler.h"

View File

@ -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 * 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 * 49 49 99 40 17 81 18 57 60 87 17 40 98 43 69 48 04 56 62 00

View File

@ -33,7 +33,7 @@ int main(int argc, char **argv)
clock_gettime(CLOCK_MONOTONIC, &end); 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"); printf("Project Euler, Problem 20\n");
gmp_printf("Answer: %Zd\n", sum); gmp_printf("Answer: %Zd\n", sum);

View File

@ -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. * 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. * 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>

View File

@ -1,5 +1,9 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
@ -7,6 +11,8 @@ def main():
sum_ = 0 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): for i in range(3, 1000):
if i % 3 == 0 or i % 5 == 0: if i % 3 == 0 or i % 5 == 0:
sum_ += i sum_ += i

View File

@ -1,17 +1,27 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
start = default_timer() start = default_timer()
N = 4000000
fib1 = 1 fib1 = 1
fib2 = 2 fib2 = 2
fibn = fib1 + fib2 fibn = fib1 + fib2
sum_ = 2 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: if fibn % 2 == 0:
sum_ = sum_ + fibn sum_ = sum_ + fibn

View File

@ -1,24 +1,39 @@
#!/usr/bin/python3 #!/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 math import floor, sqrt
from timeit import default_timer from timeit import default_timer
from projecteuler import is_prime 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): def max_prime_factor(num):
# Use function defined in projecteuler.py to check if a number is prime.
if is_prime(num): if is_prime(num):
return num return num
# If num is even, find the largest prime factor of num/2.
if num % 2 == 0: if num % 2 == 0:
return max_prime_factor(num // 2) return max_prime_factor(num // 2)
else: 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 num % i == 0:
if is_prime(i): 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(): def main():
start = default_timer() start = default_timer()

View File

@ -1,5 +1,9 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import is_palindrome from projecteuler import is_palindrome
@ -8,9 +12,13 @@ def main():
max_ = 0 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 i in range(999, 99, -1):
for j in range(i, 99, -1): for j in range(i, 99, -1):
num = i * j 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): if num > max_ and is_palindrome(num, 10):
max_ = num max_ = num

View File

@ -1,5 +1,9 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import lcmm from projecteuler import lcmm
@ -9,6 +13,7 @@ def main():
values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, values = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
11, 12, 13, 14, 15, 16, 17, 18, 19, 20) 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) res = lcmm(values, 20)
end = default_timer() end = default_timer()

View File

@ -1,12 +1,26 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
start = default_timer() start = default_timer()
sum_squares = 0 sum_squares = 0
square_sum = 0 square_sum = 0
# Straightforward brute-force approach.
for i in range(1, 101): for i in range(1, 101):
sum_squares = sum_squares + i * i sum_squares = sum_squares + i * i
square_sum = square_sum + i square_sum = square_sum + i

View File

@ -1,5 +1,9 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import is_prime from projecteuler import is_prime
@ -9,9 +13,12 @@ def main():
count = 1 count = 1
n = 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: while count != 10001:
n = n + 2 n = n + 2
# Use the function in projecteuler.py to check if a number is prime.
if is_prime(n): if is_prime(n):
count = count + 1 count = count + 1

View File

@ -1,5 +1,30 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
@ -25,10 +50,12 @@ def main():
'05886116467109405077541002256983155200055935729725' +\ '05886116467109405077541002256983155200055935729725' +\
'71636269561882670428252483600823257530420752963450' '71636269561882670428252483600823257530420752963450'
# Transform the string into a list of integers
number = list(map(int, number)) number = list(map(int, number))
max_ = 0 max_ = 0
# Calculate all the 13-digit products, and save the maximum
for i in range(1000-13): for i in range(1000-13):
curr = number[i:i+13] curr = number[i:i+13]
prod = 1 prod = 1

View File

@ -1,5 +1,15 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
@ -9,6 +19,8 @@ def main():
m = 2 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: while not found:
for n in range(1, m): for n in range(1, m):
a = m * m - n * n a = m * m - n * n

View File

@ -1,5 +1,9 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import sieve from projecteuler import sieve
@ -8,9 +12,12 @@ def main():
N = 2000000 N = 2000000
# Use the function in projecteuler.py implementing the
# Sieve of Eratosthenes algorithm to generate primes.
primes = sieve(N) primes = sieve(N)
sum_ = 0 sum_ = 0
# Sum all the primes
for i in range(N): for i in range(N):
if primes[i] == 1: if primes[i] == 1:
sum_ = sum_ + i sum_ = sum_ + i

View File

@ -1,5 +1,32 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
@ -28,11 +55,14 @@ def main():
max_ = 0 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 i in range(17):
for j in range(17): for j in range(17):
# Horizontal direction.
prod = 1 prod = 1
k = j k = j
while k < j + 4: while k < j + 4:
prod = prod * grid[i][k] prod = prod * grid[i][k]
k = k + 1 k = k + 1
@ -40,9 +70,9 @@ def main():
if prod > max_: if prod > max_:
max_ = prod max_ = prod
# Vertical direction.
prod = 1 prod = 1
k = i k = i
while k < i + 4: while k < i + 4:
prod = prod * grid[k][j] prod = prod * grid[k][j]
k = k + 1 k = k + 1
@ -50,6 +80,7 @@ def main():
if prod > max_: if prod > max_:
max_ = prod max_ = prod
# Diagonal direction, from top left to bottom right.
prod = 1 prod = 1
k = i k = i
w = j w = j
@ -62,8 +93,10 @@ def main():
if prod > max_: if prod > max_:
max_ = prod max_ = prod
# The last diagonal is handled separately
for i in range(17): for i in range(17):
for j in range(3, 20): for j in range(3, 20):
# Diagonal direction, from top right to bottom left.
prod = 1 prod = 1
k = i k = i
w = j w = j

View File

@ -1,5 +1,24 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import count_divisors from projecteuler import count_divisors
@ -10,10 +29,12 @@ def main():
triang = 0 triang = 0
finished = 0 finished = 0
# Generate all triangle numbers until the first one with more than 500 divisors is found.
while not finished: while not finished:
i = i + 1 i = i + 1
triang = triang + i triang = triang + i
# Use the function implemented in projecteuler.py to count divisors of a number.
if count_divisors(triang) > 500: if count_divisors(triang) > 500:
finished = 1 finished = 1

View File

@ -1,5 +1,108 @@
#!/usr/bin/python3 #!/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 import numpy as np
from timeit import default_timer from timeit import default_timer
@ -108,6 +211,7 @@ def main():
20849603980134001723930671666823555245252804609722, 20849603980134001723930671666823555245252804609722,
53503534226472524250874054075591789781264330331690] 53503534226472524250874054075591789781264330331690]
# Convert the list of numbers in a numpy array and calculate the sum
numbers = np.array(numbers) numbers = np.array(numbers)
sum_ = str(numbers.sum()) sum_ = str(numbers.sum())

View File

@ -1,15 +1,39 @@
#!/usr/bin/python3 #!/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 numpy import zeros
from timeit import default_timer 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): def collatz_length(n):
if n == 1: if n == 1:
return 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] return collatz_found[n]
if n % 2 == 0: if n % 2 == 0:
@ -23,7 +47,9 @@ def main():
max_l = 0 max_l = 0
max_ = 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) count = collatz_length(i)
collatz_found[i] = count collatz_found[i] = count

View File

@ -1,5 +1,8 @@
#!/usr/bin/python3 #!/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 math import factorial
from timeit import default_timer from timeit import default_timer
@ -7,6 +10,10 @@ from timeit import default_timer
def main(): def main():
start = default_timer() 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) count = factorial(40)
tmp = factorial(20) tmp = factorial(20)
tmp = tmp * tmp tmp = tmp * tmp

View File

@ -1,10 +1,16 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
start = default_timer() start = default_timer()
# Simply calculate 2^1000, convert the result to string and calculate
# the sum of the digits
res = str(2 ** 1000) res = str(2 ** 1000)
sum_ = 0 sum_ = 0

View File

@ -1,32 +1,59 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
start = default_timer() 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],\ 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],\ [6, 6, 5, 5, 5, 7, 6, 6],\
[1300, 1300, 1500, 1400, 1400, 1300, 1500, 1500, 1400],\ [13, 13, 15, 14, 14, 13, 15, 15, 14],\
[11]] [11]]
sum_ = 0 sum_ = 0
# Sum the letters of the first 19 numbers.
for i in range(19): for i in range(19):
sum_ = sum_ + n_letters[0][i] sum_ = sum_ + n_letters[0][i]
# Add the letters of the numbers from 20 to 99.
for i in range(8): 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): for j in range(9):
n_letters[1][i] = n_letters[1][i] + n_letters[0][j] n_letters[1][i] = n_letters[1][i] + n_letters[0][j]
sum_ = sum_ + n_letters[1][i] sum_ = sum_ + n_letters[1][i]
# Add the letters of the numbers from 100 to 999.
for i in range(9): 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): for j in range(19):
n_letters[2][i] = n_letters[2][i] + n_letters[0][j] n_letters[2][i] = n_letters[2][i] + n_letters[0][j]
# Add "twenty" to "ninety nine", previously calculated.
for j in range(8): for j in range(8):
n_letters[2][i] = n_letters[2][i] + n_letters[1][j] 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 sum_ = sum_ + n_letters[2][i] - 3
# Add "one thousand".
sum_ = sum_ + n_letters[3][0] sum_ = sum_ + n_letters[3][0]
end = default_timer() end = default_timer()

View File

@ -1,5 +1,35 @@
#!/usr/bin/python3 #!/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 timeit import default_timer
from projecteuler import find_max_path from projecteuler import find_max_path
@ -24,6 +54,7 @@ def main():
for i in range(l): for i in range(l):
triang[i] = list(map(int, triang[i])) triang[i] = list(map(int, triang[i]))
# Use function implemented in projecteuler.c to find the maximum path.
max_ = find_max_path(triang, 15) max_ = find_max_path(triang, 15)
end = default_timer() end = default_timer()

View File

@ -1,5 +1,18 @@
#!/usr/bin/python3 #!/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 import datetime
from timeit import default_timer from timeit import default_timer
@ -9,6 +22,7 @@ def main():
count = 0 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 year in range(1901, 2001):
for month in range(1, 13): for month in range(1, 13):
if datetime.datetime(year, month, 1).weekday() == 6: if datetime.datetime(year, month, 1).weekday() == 6:

View File

@ -1,5 +1,12 @@
#!/usr/bin/python3 #!/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 math import factorial
from timeit import default_timer from timeit import default_timer
@ -7,6 +14,7 @@ from timeit import default_timer
def main(): def main():
start = default_timer() start = default_timer()
# Calculate the factorial, convert the result to string and sum the digits.
n = str(factorial(100)) n = str(factorial(100))
sum_ = 0 sum_ = 0

View File

@ -1,21 +1,17 @@
#!/usr/bin/python3 #!/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 math import floor, sqrt
from timeit import default_timer from timeit import default_timer
from projecteuler import sum_of_divisors
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_
def main(): def main():
start = default_timer() start = default_timer()
@ -23,7 +19,11 @@ def main():
sum_ = 0 sum_ = 0
for i in range(2, 10000): for i in range(2, 10000):
# Calculate the sum of proper divisors with the function
# implemented in projecteuler.py.
n = sum_of_divisors(i) 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: if i != n and sum_of_divisors(n) == i:
sum_ = sum_ + i + n sum_ = sum_ + i + n

View File

@ -1,5 +1,13 @@
#!/usr/bin/python3 #!/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 from timeit import default_timer
def main(): def main():
@ -17,6 +25,7 @@ def main():
sum_ = 0 sum_ = 0
i = 1 i = 1
# Calculate the score of each name an multiply by its position.
for name in names: for name in names:
l = len(name) l = len(name)
score = 0 score = 0

View File

@ -1,31 +1,39 @@
#!/usr/bin/python3 #!/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 math import floor, sqrt
from timeit import default_timer from timeit import default_timer
from projecteuler import sum_of_divisors
def is_abundant(n): def is_abundant(n):
limit = floor(sqrt(n)) + 1 return sum_of_divisors(n) > n
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
def main(): def main():
start = default_timer() start = default_timer()
ab_nums = [False] * 28124 ab_nums = [False] * 28124
# Find all abundant numbers smaller than 28123.
for i in range(12, 28124): for i in range(12, 28124):
ab_nums[i] = is_abundant(i) ab_nums[i] = is_abundant(i)
sums = [False] * 28124 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): for i in range(1, 28123):
if ab_nums[i]: if ab_nums[i]:
for j in range(i, 28123): for j in range(i, 28123):
@ -36,6 +44,7 @@ def main():
sum_ = 0 sum_ = 0
# Sum every number that was not found as a sum of two abundant numbers.
for i in range(1, 28124): for i in range(1, 28124):
if not sums[i]: if not sums[i]:
sum_ = sum_ + i sum_ = sum_ + i

View File

@ -1,5 +1,12 @@
#!/usr/bin/python3 #!/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 itertools import permutations
from timeit import default_timer from timeit import default_timer
@ -7,6 +14,7 @@ from timeit import default_timer
def main(): def main():
start = default_timer() start = default_timer()
# Generate all the permutations in lexicographic order and get the millionth one.
perm = list(permutations('0123456789')) perm = list(permutations('0123456789'))
res = int(''.join(map(str, perm[999999]))) res = int(''.join(map(str, perm[999999])))

View File

@ -1,5 +1,26 @@
#!/usr/bin/python3 #!/usr/bin/python3
# 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 index of the first term in the Fibonacci sequence to contain 1000 digits?
from timeit import default_timer from timeit import default_timer
def main(): def main():
@ -11,6 +32,7 @@ def main():
i = 3 i = 3
# Calculate the Fibonacci numbers until one with 1000 digits is found.
while len(str(fibn)) < 1000: while len(str(fibn)) < 1000:
fib1 = fib2 fib1 = fib2
fib2 = fibn fib2 = fibn

View File

@ -6,17 +6,26 @@ from numpy import ndarray, zeros
def is_prime(num): def is_prime(num):
if num < 4: if num < 4:
# If num is 2 or 3 then it's prime.
return num == 2 or num == 3 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: if num % 2 == 0 or num % 3 == 0:
return False 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 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): for i in range(5, limit, 6):
if num % i == 0 or num % (i + 2) == 0: if num % i == 0 or num % (i + 2) == 0:
return False return False
# If no factor is found up to the square root of num, num is prime.
return True return True
def is_palindrome(num, base): def is_palindrome(num, base):
@ -24,44 +33,64 @@ def is_palindrome(num, base):
tmp = num 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: while tmp > 0:
reverse = reverse * base reverse = reverse * base
reverse = reverse + tmp % base reverse = reverse + tmp % base
tmp = tmp // base tmp = tmp // base
# If the reversed number is equal to the original one, then it's palindrome.
if num == reverse: if num == reverse:
return True return True
return False return False
# Least common multiple algorithm using the greatest common divisor.
def lcm(a, b): def lcm(a, b):
return a * b // gcd(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): def lcmm(values, n):
# If there are only two numbers, use the lcm function to calculate the lcm.
if n == 2: if n == 2:
return lcm(values[0], values[1]) return lcm(values[0], values[1])
value = values[0] value = values[0]
for i in range(1, n): # Recursively calculate lcm(a, b, c, ..., n) = lcm(a, lcm(b, c, ..., n)).
return lcm(value, lcmm(values[i:], n-1)) 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): def sieve(n):
primes = ndarray((n,), int) primes = ndarray((n,), int)
# 0 and 1 are not prime, 2 and 3 are prime.
primes[0] = 0 primes[0] = 0
primes[1] = 0 primes[1] = 0
primes[2] = 1 primes[2] = 1
primes[3] = 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): for i in range(4, n -1, 2):
primes[i] = 0 primes[i] = 0
primes[i+1] = 1 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)) limit = floor(sqrt(n))
for i in range(3, limit, 2): for i in range(3, limit, 2):
# Find the next number not crossed out, which is prime.
if primes[i] == 1: 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): for j in range(i * i, n, 2 * i):
primes[j] = 0 primes[j] = 0
@ -69,6 +98,10 @@ def sieve(n):
def count_divisors(n): def count_divisors(n):
count = 0 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)) limit = floor(sqrt(n))
for i in range(1, limit): for i in range(1, limit):
@ -81,7 +114,11 @@ def count_divisors(n):
return count return count
def find_max_path(triang, n): 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 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): for j in range(0, i+1):
if triang[i+1][j] > triang[i+1][j+1]: if triang[i+1][j] > triang[i+1][j+1]:
triang[i][j] = triang[i][j] + triang[i+1][j] triang[i][j] = triang[i][j] + triang[i+1][j]
@ -90,6 +127,26 @@ def find_max_path(triang, n):
return triang[0][0] 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): def is_pandigital(value, n):
i = 0 i = 0
digits = zeros(n + 1, int) digits = zeros(n + 1, int)
@ -116,6 +173,8 @@ def is_pandigital(value, n):
return True return True
def is_pentagonal(n): 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 i = (sqrt(24*n+1) + 1) / 6
return i.is_integer() return i.is_integer()