diff --git a/C/p032.c b/C/p032.c index 515f17c..8bd48a6 100644 --- a/C/p032.c +++ b/C/p032.c @@ -17,7 +17,7 @@ int compare(void *a, void *b); int main(int argc, char **argv) { - int a, b, i, j, p, sum, n = 0, num; + int i, j, p, sum, n = 0, num; int **products; char num_s[10]; double elapsed; diff --git a/C/p035.c b/C/p035.c index 7ab218f..0e4156a 100644 --- a/C/p035.c +++ b/C/p035.c @@ -88,7 +88,7 @@ int is_circular_prime(int n) for(i = 1; i < count; i++) { - /* Generate rotations and check if it's primes.*/ + /* Generate rotations and check if they're prime.*/ n = n % (int)pow(10, count-1) * 10 + n / (int)pow(10, count-1); if(primes[n] == 0) { diff --git a/C/p038.c b/C/p038.c index 0299c66..917a7a9 100644 --- a/C/p038.c +++ b/C/p038.c @@ -8,8 +8,8 @@ * * The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, and 5, giving the pandigital, 918273645, which is the concatenated * product of 9 and (1,2,3,4,5). - -What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1?*/ + * + * What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1?*/ #include #include diff --git a/C/p041.c b/C/p041.c index 348302c..8c2cb6b 100644 --- a/C/p041.c +++ b/C/p041.c @@ -30,7 +30,7 @@ int main(int argc, char **argv) { break; } -// Skipping the even numbers. + /*Skipping the even numbers.*/ i -= 2; } diff --git a/Python/p026.py b/Python/p026.py index e00f35e..42a895c 100644 --- a/Python/p026.py +++ b/Python/p026.py @@ -1,5 +1,21 @@ #!/usr/bin/python3 +# A unit fraction contains 1 in the numerator. The decimal representation of the unit fractions with denominators 2 to 10 are given: +# +# 1/2 = 0.5 +# 1/3 = 0.(3) +# 1/4 = 0.25 +# 1/5 = 0.2 +# 1/6 = 0.1(6) +# 1/7 = 0.(142857) +# 1/8 = 0.125 +# 1/9 = 0.(1) +# 1/10 = 0.1 +# +# Where 0.1(6) means 0.166666..., and has a 1-digit recurring cycle. It can be seen that 1/7 has a 6-digit recurring cycle. +# +# Find the value of d < 1000 for which 1/d contains the longest recurring cycle in its decimal fraction part. + from timeit import default_timer def main(): @@ -10,19 +26,27 @@ def main(): for i in range(2, 1000): j = i +# The repeating cycle of 1/(2^a*5^b*p^c*...) is equal to +# that of 1/p^c*..., so factors 2 and 5 can be eliminated. while j % 2 == 0 and j > 1: j = j // 2 while j % 5 == 0 and j > 1: j = j // 5 - k = 9 - +# If the denominator had only factors 2 and 5, there is no +# repeating cycle. if j == 1: n = 0 else: n = 1 + k = 9 div = j + +# After eliminating factors 2s and 5s, the length of the repeating cycle +# of 1/d is the smallest n for which k=10^n-1/d is an integer. So we start +# with k=9, then k=99, k=999 and so on until k is divisible by d. +# The number of digits of k is the length of the repeating cycle. while k % div != 0: n = n + 1 k = k * 10 diff --git a/Python/p027.py b/Python/p027.py index 53ea103..05dd5b1 100644 --- a/Python/p027.py +++ b/Python/p027.py @@ -1,5 +1,24 @@ #!/usr/bin/python3 +# Euler discovered the remarkable quadratic formula: +# +# n^2+n+41 +# +# It turns out that the formula will produce 40 primes for the consecutive integer values 0≤n≤39. However, when n=40,402+40+41=40(40+1)+41 is +# divisible by 41, and certainly when n=41,412+41+41 is clearly divisible by 41. +# +# The incredible formula n^2−79n+1601 was discovered, which produces 80 primes for the consecutive values 0≤n≤79. +# The product of the coefficients, −79 and 1601, is −126479. +# +# Considering quadratics of the form: +# +# n^2+an+b, where |a|<1000 and |b|≤1000 +# +# where |n| is the modulus/absolute value of n +# e.g. |11|=11 and |−4|=4 +# +# Find the product of the coefficients, a and b, for the quadratic expression that produces the maximum number of primes for consecutive values of n, starting with n=0. + from timeit import default_timer from projecteuler import is_prime @@ -8,24 +27,27 @@ def main(): max_ = 0 +# Brute force approach, optimized by checking only values of b where b is prime. for a in range(-999, 1000): for b in range(2, 1001): - n = 0 - count = 0 +# For n=0, n^2+an+b=b, so b must be prime. + if is_prime(b): + n = 0 + count = 0 - while True: - p = n * n + a * n + b + while True: + p = n * n + a * n + b - if p > 1 and is_prime(p): - count = count + 1 - n = n + 1 - else: - break + if p > 1 and is_prime(p): + count = count + 1 + n = n + 1 + else: + break - if count > max_: - max_ = count - save_a = a - save_b = b + if count > max_: + max_ = count + save_a = a + save_b = b end = default_timer() diff --git a/Python/p028.py b/Python/p028.py index 8ad1c49..60d0b03 100644 --- a/Python/p028.py +++ b/Python/p028.py @@ -1,5 +1,17 @@ #!/usr/bin/python3 +# Starting with the number 1 and moving to the right in a clockwise direction a 5 by 5 spiral is formed as follows: +# +# 21 22 23 24 25 +# 20 7 8 9 10 +# 19 6 1 2 11 +# 18 5 4 3 12 +# 17 16 15 14 13 +# +# It can be verified that the sum of the numbers on the diagonals is 101. +# +# What is the sum of the numbers on the diagonals in a 1001 by 1001 spiral formed in the same way? + from timeit import default_timer def main(): @@ -14,6 +26,10 @@ def main(): step = 0 sum_ = 1 +# Starting with the central 1, it's easy to see that the next four numbers in the diagonal +# are 1+2, 1+2+2, 1+2+2+2 and 1+2+2+2+2, then for the next four number the step is increased +# by two, so from 9 to 9+4, 9+4+4 etc, for the next four number the step is again increased +# by two, and so on. We go on until the value is equal to N*N, with N=1001 for this problem. while j < limit: if i == 0: step = step + 2 diff --git a/Python/p029.py b/Python/p029.py index 5cfdc59..34bb6b2 100644 --- a/Python/p029.py +++ b/Python/p029.py @@ -1,5 +1,18 @@ #!/usr/bin/python3 +# Consider all integer combinations of ab 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 ab for 2 ≤ a ≤ 100 and 2 ≤ b ≤ 100? + from numpy import zeros from timeit import default_timer @@ -9,11 +22,13 @@ def main(): powers = zeros(9801) +# Generate all the powers for i in range(2, 101): a = i for j in range(2, 101): powers[(i-2)*99+j-2] = a ** j +# Sort the values and count the different values. powers = list(powers) powers.sort() diff --git a/Python/p030.py b/Python/p030.py index c0e86a1..5bf0bbd 100644 --- a/Python/p030.py +++ b/Python/p030.py @@ -1,5 +1,17 @@ #!/usr/bin/python3 +# 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 = 1^4 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. + from timeit import default_timer def main(): @@ -7,6 +19,9 @@ def main(): tot = 0 +# Straightforward brute force approach. The limit is chosen considering that +# 6*9^5=354294, so no number larger than that can be expressed as sum +# of 5th power of its digits. for i in range(10, 354295): j = i sum_ = 0 diff --git a/Python/p031.py b/Python/p031.py index 51e2e4a..b160183 100644 --- a/Python/p031.py +++ b/Python/p031.py @@ -1,7 +1,18 @@ #!/usr/bin/python3 +# In England the currency is made up of pound, £, and pence, p, and there are eight coins in general circulation: +# +# 1p, 2p, 5p, 10p, 20p, 50p, £1 (100p) and £2 (200p). +# +# It is possible to make £2 in the following way: +# +# 1×£1 + 1×50p + 2×20p + 1×5p + 1×2p + 3×1p +# +# How many different ways can £2 be made using any number of coins? + from timeit import default_timer +# Simple recursive function that tries every combination. def count(coins, value, n, i): for j in range(i, 8): value = value + coins[j] diff --git a/Python/p032.py b/Python/p032.py index 8297c18..76c7411 100644 --- a/Python/p032.py +++ b/Python/p032.py @@ -1,66 +1,79 @@ #!/usr/bin/python3 +# We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once; for example, the 5-digit number, 15234, +# is 1 through 5 pandigital. +# +# The product 7254 is unusual, as the identity, 39 × 186 = 7254, containing multiplicand, multiplier, and product is 1 through 9 pandigital. +# +# Find the sum of all products whose multiplicand/multiplier/product identity can be written as a 1 through 9 pandigital. +# +# HINT: Some products can be obtained in more than one way so be sure to only include it once in your sum. + import numpy as np from numpy import zeros from timeit import default_timer +from projecteuler import is_pandigital def main(): start = default_timer() n = 0 - products = zeros(100, int) +# Initially I used a bigger array, but printing the resulting products +# shows that 10 values are sufficient. + products = zeros(10, int) - for i in range(2, 100): - for j in range(100, 10000): - a = i - b = j - p = a * b +# To get a 1 to 9 pandigital concatenation of the two factors and product, +# we need to multiply a 1 digit number times a 4 digit numbers (the biggest +# one digit number 9 times the biggest 3 digit number 999 multiplied give +# 8991 and the total digit count is 8, which is not enough), or a 2 digit +# number times a 3 digit number (the smallest two different 3 digits number, +# 100 and 101, multiplied give 10100, and the total digit count is 11, which +# is too many). The outer loop starts at 2 because 1 times any number gives +# the same number, so its digit will be repeated and the result can't be +# pandigital. The nested loop starts from 1234 because it's the smallest +# 4-digit number with no repeated digits, and it ends at 4987 because it's +# the biggest number without repeated digits that multiplied by 2 gives a +# 4 digit number. + for i in range(2, 9): + for j in range(1234, 4987): + p = i * j + num_s = str(i) + str(j) + str(p) - digits = zeros(10, int) + if len(num_s) > 9: + break - while True: - d = a % 10 - digits[d] = digits[d] + 1 - a = a // 10 + num = int(num_s) - if a <= 0: - break - - while True: - d = b % 10 - digits[d] = digits[d] + 1 - b = b // 10 - - if b <= 0: - break - - p1 = p - - while True: - d = p1 % 10 - digits[d] = digits[d] + 1 - p1 = p1 // 10 - - if p1 <= 0: - break - - k = 0 - - if digits[0] == 0: - for k in range(1, 11): - if k > 9 or digits[k] > 1 or digits[k] == 0: - break - - if k == 10: + if is_pandigital(num, 9): products[n] = p n = n + 1 - products = np.sort(products) +# The outer loop starts at 12 because 10 has a 0 and 11 has two 1s, so +# the result can't be pandigital. The nested loop starts at 123 because +# it's the smallest 3-digit number with no digit repetitions and ends at +# 833, because 834*12 has 5 digits. + for i in range(12, 99): + for j in range(123, 834): + p = i * j + + num_s = str(i) + str(j) + str(p) + + if len(num_s) > 9: + break + + num = int(num_s) + + if is_pandigital(num, 9): + products[n] = p + n = n + 1 + +# Sort the found products to easily see if there are duplicates. + products = np.sort(products[:n]) sum_ = products[0] - for i in range(1, 100): + for i in range(1, n): if products[i] != products[i-1]: sum_ = sum_ + products[i] diff --git a/Python/p033.py b/Python/p033.py index 722cab1..2243a3c 100644 --- a/Python/p033.py +++ b/Python/p033.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# The fraction 49/98 is a curious fraction, as an inexperienced mathematician in attempting to simplify it may incorrectly believe that 49/98 = 4/8, +# which is correct, is obtained by cancelling the 9s. +# +# We shall consider fractions like, 30/50 = 3/5, to be trivial examples. +# +# There are exactly four non-trivial examples of this type of fraction, less than one in value, and containing two digits in the numerator +# and denominator. +# +# If the product of these four fractions is given in its lowest common terms, find the value of the denominator. + from timeit import default_timer from projecteuler import gcd @@ -11,6 +21,8 @@ def main(): for i in range(11, 100): for j in range(11, 100): +# If the example is non-trivial, check if cancelling the digit that's equal +# in numerator and denominator gives the same fraction. if i % 10 != 0 and j % 10 != 0 and\ i != j and i % 10 == j // 10: n = i // 10 @@ -23,6 +35,7 @@ def main(): prod_n = prod_n * i prod_d = prod_d * j +# Find the greater common divisor of the fraction found. div = gcd(prod_n, prod_d) end = default_timer() diff --git a/Python/p034.py b/Python/p034.py index 3ffb5a7..6b9e392 100644 --- a/Python/p034.py +++ b/Python/p034.py @@ -1,5 +1,11 @@ #!/usr/bin/python3 +# 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. + from math import factorial from numpy import ones @@ -13,10 +19,12 @@ def main(): sum_ = 0 factorials = ones(10, int) +# Pre-calculate factorials of each digit from 0 to 9. for i in range(2, 10): factorials[i] = factorial(i) - while a < 50000: +# 9!*7<9999999, so 9999999 is certainly un upper bound. + while a < 9999999: b = a sum_f = 0 diff --git a/Python/p035.py b/Python/p035.py index c5fbc06..307c3b3 100644 --- a/Python/p035.py +++ b/Python/p035.py @@ -1,24 +1,39 @@ #!/usr/bin/python3 +# 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 timeit import default_timer from projecteuler import sieve def is_circular_prime(n): global primes +# If n is not prime, it's obviously not a circular prime. if primes[n] == 0: return False +# The primes below 10 are circular primes. + if primes[n] == 1 and n < 10: + return True + tmp = n count = 0 +# If the number has one or more even digits, it can't be a circular prime. +# because at least one of the rotations will be even. while tmp > 0: if tmp % 2 == 0: return False +# Count the number of digits. count = count + 1 tmp = tmp // 10 for i in range(1, count): +# Generate rotations and check if they're prime. n = n % (10 ** (count - 1)) * 10 + n // (10 ** (count - 1)) if primes[n] == 0: @@ -33,9 +48,11 @@ def main(): N = 1000000 +# Calculate all primes below one million, then check if they're circular. primes = sieve(N) count = 13 +# Calculate all primes below one million, then check if they're circular. for i in range(101, N, 2): if is_circular_prime(i): count = count + 1 diff --git a/Python/p036.py b/Python/p036.py index 746c068..47a1713 100644 --- a/Python/p036.py +++ b/Python/p036.py @@ -1,14 +1,25 @@ #!/usr/bin/python3 +# The decimal number, 585 = 1001001001_2 (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.) + from timeit import default_timer from projecteuler import is_palindrome def main(): start = default_timer() + N = 1000000 + sum_ = 0 - for i in range(1, 1000000): +# Brute force approach. For every number below 1 million, +# check if they're palindrome in base 2 and 10 using the +# function implemented in projecteuler.c. + for i in range(1, N): if is_palindrome(i, 10) and is_palindrome(i, 2): sum_ = sum_ + i diff --git a/Python/p037.py b/Python/p037.py index e2c3708..f7bec24 100644 --- a/Python/p037.py +++ b/Python/p037.py @@ -1,19 +1,33 @@ #!/usr/bin/python3 +# The number 3797 has an interesting property. Being prime itself, it is possible to continuously remove digits from left to right, +# and remain prime at each stage: 3797, 797, 97, and 7. Similarly we can work from right to left: 3797, 379, 37, and 3. +# +# Find the sum of the only eleven primes that are both truncatable from left to right and right to left. +# +# NOTE: 2, 3, 5, and 7 are not considered to be truncatable primes. + from timeit import default_timer from projecteuler import is_prime def is_tr_prime(n): +# One-digit numbers and non-prime numbers are +# not truncatable primes. if n < 11 or not is_prime(n): return False tmp = n // 10 +# Remove one digit at a time from the right and check +# if the resulting number is prime. Return 0 if it isn't. while tmp > 0: if not is_prime(tmp): return False tmp = tmp // 10 +# Starting from the last digit, check if it's prime, then +# add back one digit at a time on the left and check if it +# is prime. Return 0 when it isn't. i = 10 tmp = n % i @@ -23,6 +37,7 @@ def is_tr_prime(n): i = i * 10 tmp = n % i +# If it gets here, the number is truncatable prime. return True def main(): @@ -32,6 +47,7 @@ def main(): n = 1 sum_ = 0 +# Check every number until 11 truncatable primes are found. while i < 11: if is_tr_prime(n): sum_ = sum_ + n diff --git a/Python/p038.py b/Python/p038.py index 01fb820..7412b68 100644 --- a/Python/p038.py +++ b/Python/p038.py @@ -1,5 +1,18 @@ #!/usr/bin/python3 +# Take the number 192 and multiply it by each of 1, 2, and 3: +# +# 192 × 1 = 192 +# 192 × 2 = 384 +# 192 × 3 = 576 +# +# By concatenating each product we get the 1 to 9 pandigital, 192384576. We will call 192384576 the concatenated product of 192 and (1,2,3) +# +# The same can be achieved by starting with 9 and multiplying by 1, 2, 3, 4, and 5, giving the pandigital, 918273645, which is the concatenated +# product of 9 and (1,2,3,4,5). +# +# What is the largest 1 to 9 pandigital 9-digit number that can be formed as the concatenated product of an integer with (1,2, ... , n) where n > 1? + from numpy import zeros from timeit import default_timer @@ -10,6 +23,12 @@ def main(): max_ = 0 +# A brute force approach is used, starting with 1 and multiplying +# the number by 1, 2 etc., concatenating the results, checking if +# it's 1 to 9 pandigital, and going to the next number when the +# concatenated result is greater than the greatest 9 digit pandigital +# value. The limit is set to 10000, since 1*10000=10000, 2*10000=20000 and +# concatenating this two numbers a 10-digit number is obtained. for i in range(1, 10000): n = 0 j = 1 diff --git a/Python/p039.py b/Python/p039.py index 484b0aa..906f051 100644 --- a/Python/p039.py +++ b/Python/p039.py @@ -1,5 +1,11 @@ #!/usr/bin/python3 +# If p is the perimeter of a right angle triangle with integral length sides, {a,b,c}, there are exactly three solutions for p = 120. +# +# {20,48,52}, {24,45,51}, {30,40,50} +# +# For which value of p ≤ 1000, is the number of solutions maximised? + from numpy import zeros from timeit import default_timer @@ -10,6 +16,7 @@ def main(): max_ = 0 savedc = zeros(1000, int) +# Start with p=12 (the smallest pythagorean triplet is (3,4,5) and 3+4+5=12. for p in range(12, 1001): count = 0 a = 0 @@ -17,12 +24,16 @@ def main(): c = 0 m = 2 +# Generate pythagorean triplets. while m * m < p: for n in range(1, m): a = m * m - n * n b = 2 * m * n c = m * m + n * n +# Increase counter if a+b+c=p and the triplet is new, +# then save the value of c to avoid counting the same +# triplet more than once. if a + b + c == p and savedc[c] == 0: savedc[c] = 1 count = count + 1 @@ -32,11 +43,14 @@ def main(): tmpb = b tmpc = c +# Check all the triplets obtained multiplying a, b and c +# for integer numbers, until the perimeters exceeds p. while tmpa + tmpb + tmpc < p: tmpa = a * i tmpb = b * i tmpc = c * i +# Increase counter if the new a, b and c give a perimeter=p. if tmpa + tmpb + tmpc == p and savedc[tmpc] == 0: savedc[tmpc] = 1 count = count + 1 @@ -45,6 +59,8 @@ def main(): m = m + 1 +# If the current value is greater than the maximum, +# save the new maximum and the value of p. if count > max_: max_ = count res = p diff --git a/Python/p040.py b/Python/p040.py index 0299e76..95ff515 100644 --- a/Python/p040.py +++ b/Python/p040.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# An irrational decimal fraction is created by concatenating the positive integers: +# +# 0.123456789101112131415161718192021... +# +# It can be seen that the 12th digit of the fractional part is 1. +# +# If d_n represents the nth digit of the fractional part, find the value of the following expression. +# +# d_1 × d_10 × d_100 × d_1000 × d_10000 × d_100000 × d_1000000 + from numpy import zeros from timeit import default_timer @@ -11,6 +21,9 @@ def main(): i = 1 value = 1 +# Loop on all numbers and put the digits in the right place +# in an array. Use modulo and division to get the digits +# for numbers with more than one digit. while i <= 1000000: if value < 10: digits[i-1] = value @@ -47,6 +60,7 @@ def main(): i = i + 6 value = value + 1 +# Calculate the product. n = digits[0] * digits[9] * digits[99] * digits[999] * digits[9999] * digits[99999] * digits[999999] end = default_timer() diff --git a/Python/p041.py b/Python/p041.py index 2219140..09996fb 100644 --- a/Python/p041.py +++ b/Python/p041.py @@ -1,5 +1,10 @@ #!/usr/bin/python3 +# We shall say that an n-digit number is pandigital if it makes use of all the digits 1 to n exactly once. For example, 2143 is a 4-digit pandigital +# and is also prime. +# +# What is the largest n-digit pandigital prime that exists? + from timeit import default_timer from projecteuler import is_pandigital, is_prime @@ -15,11 +20,17 @@ def count_digits(n): def main(): start = default_timer() +# 8- and 9-digit pandigital numbers can't be prime, because +# 1+2+...+8=36, which is divisible by 3, and 36+9=45 which is +# also divisible by 3, and therefore the whole number is divisible +# by 3. So we can start from the largest 7-digit pandigital number, +# until we find a prime. i = 7654321 while(i > 0): if is_pandigital(i, count_digits(i)) and is_prime(i): break +# Skipping the even numbers. i = i - 2 end = default_timer() diff --git a/Python/p042.py b/Python/p042.py index 70bc439..80048ab 100644 --- a/Python/p042.py +++ b/Python/p042.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# The nth term of the sequence of triangle numbers is given by, tn = ½n(n+1); so the first ten triangle numbers are: +# +# 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ... +# +# By converting each letter in a word to a number corresponding to its alphabetical position and adding these values we form a word value. +# For example, the word value for SKY is 19 + 11 + 25 = 55 = t10. If the word value is a triangle number then we shall call the word a triangle word. +# +# Using words.txt (right click and 'Save Link/Target As...'), a 16K text file containing nearly two-thousand common English words, +# how many are triangle words? + from timeit import default_timer def is_triang(n): @@ -29,6 +39,7 @@ def main(): count = 0 +# For each word, calculate its value and check if it's a triangle number. for word in words: value = 0 l = len(word) diff --git a/Python/p043.py b/Python/p043.py index a12e11e..9669192 100644 --- a/Python/p043.py +++ b/Python/p043.py @@ -1,9 +1,25 @@ #!/usr/bin/python3 +# The number, 1406357289, is a 0 to 9 pandigital number because it is made up of each of the digits 0 to 9 in some order, but it also has a +# rather interesting sub-string divisibility property. +# +# Let d1 be the 1st digit, d2 be the 2nd digit, and so on. In this way, we note the following: +# +# d2d3d4=406 is divisible by 2 +# d3d4d5=063 is divisible by 3 +# d4d5d6=635 is divisible by 5 +# d5d6d7=357 is divisible by 7 +# d6d7d8=572 is divisible by 11 +# d7d8d9=728 is divisible by 13 +# d8d9d10=289 is divisible by 17 +# +# Find the sum of all 0 to 9 pandigital numbers with this property. + from itertools import permutations from timeit import default_timer +# Function to check if the value has the desired property. def has_property(n): value = int(n[1]) * 100 + int(n[2]) * 10 + int(n[3]) @@ -45,10 +61,12 @@ def has_property(n): def main(): start = default_timer() +# Find all the permutations perm = list(permutations('0123456789')) sum_ = 0 +# For each permutation, check if it has the required property for i in perm: if has_property(i): sum_ = sum_ + int(''.join(map(str, i))) diff --git a/Python/p044.py b/Python/p044.py index b9caeb9..7b4c961 100644 --- a/Python/p044.py +++ b/Python/p044.py @@ -1,5 +1,14 @@ #!/usr/bin/python3 +# Pentagonal numbers are generated by the formula, Pn=n(3n−1)/2. The first ten pentagonal numbers are: +# +# 1, 5, 12, 22, 35, 51, 70, 92, 117, 145, ... +# +# It can be seen that P4 + P7 = 22 + 70 = 92 = P8. However, their difference, 70 − 22 = 48, is not pentagonal. +# +# Find the pair of pentagonal numbers, Pj and Pk, for which their sum and difference are pentagonal and D = |Pk − Pj| is minimised; +# what is the value of D? + from math import sqrt from timeit import default_timer @@ -11,6 +20,9 @@ def main(): found = 0 n = 2 +# Check all couples of pentagonal numbers until the right one +# is found. Use the function implemented in projecteuler.py to +# check if the sum and difference ot the two numbers is pentagonal. while not found: pn = n * (3 * n - 1) // 2 diff --git a/Python/p045.py b/Python/p045.py index 4ad638b..a1dedef 100644 --- a/Python/p045.py +++ b/Python/p045.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# Triangle, pentagonal, and hexagonal numbers are generated by the following formulae: +# +# Triangle T_n=n(n+1)/2 1, 3, 6, 10, 15, ... +# Pentagonal P_n=n(3n−1)/2 1, 5, 12, 22, 35, ... +# Hexagonal H_n=n(2n−1) 1, 6, 15, 28, 45, ... +# +# It can be verified that T_285 = P_165 = H_143 = 40755. +# +# Find the next triangle number that is also pentagonal and hexagonal. + from math import sqrt from timeit import default_timer @@ -13,6 +23,9 @@ def main(): while not found: i = i + 1 +# Hexagonal numbers are also triangle numbers, so it's sufficient +# to generate hexagonal numbers (starting from H_144) and check if +# they're also pentagonal. n = i * (2 * i - 1) if is_pentagonal(n): diff --git a/Python/p046.py b/Python/p046.py index 977cc37..a249a92 100644 --- a/Python/p046.py +++ b/Python/p046.py @@ -1,15 +1,31 @@ #!/usr/bin/python3 +# It was proposed by Christian Goldbach that every odd composite number can be written as the sum of a prime and twice a square. +# +# 9 = 7 + 2×1^2 +# 15 = 7 + 2×2^2 +# 21 = 3 + 2×3^2 +# 25 = 7 + 2×3^2 +# 27 = 19 + 2×2^2 +# 33 = 31 + 2×1^2 +# +# It turns out that the conjecture was false. +# +# What is the smallest odd composite that cannot be written as the sum of a prime and twice a square? + from timeit import default_timer from projecteuler import sieve def goldbach(n): global primes +# Check every prime smaller than n. for i in range(3, n, 2): if primes[i] == 1: j = 1 +# Check if summing twice a square to the prime number +# gives n. Return 1 when succeeding. while True: tmp = i + 2 * j * j @@ -21,6 +37,7 @@ def goldbach(n): if tmp >= n: break +# Return 0 if no solution is found. return False def main(): @@ -35,6 +52,9 @@ def main(): found = 0 i = 3 +# For every odd number, check if it's prime, if it is check +# if it satisfies the Goldbach property. Continue until the +# first number that doesn't is found. while not found and i < N: if primes[i] == 0: if not goldbach(i): diff --git a/Python/p047.py b/Python/p047.py index 769baa7..d03cfed 100644 --- a/Python/p047.py +++ b/Python/p047.py @@ -1,5 +1,18 @@ #!/usr/bin/python3 +# The first two consecutive numbers to have two distinct prime factors are: +# +# 14 = 2 × 7 +# 15 = 3 × 5 +# +# The first three consecutive numbers to have three distinct prime factors are: +# +# 644 = 2² × 7 × 23 +# 645 = 3 × 5 × 43 +# 646 = 2 × 17 × 19. +# +# Find the first four consecutive integers to have four distinct prime factors each. What is the first of these numbers? + from timeit import default_timer from projecteuler import sieve @@ -7,6 +20,8 @@ def count_distinct_factors(n): global primes count = 0 +# Start checking if 2 is a prime factor of n. Then remove +# all 2s factore. if n % 2 == 0: count = count + 1 @@ -18,6 +33,10 @@ def count_distinct_factors(n): i = 3 +# Check all odd numbers i, if they're prime and they're a factor +# of n, count them and then divide n for by i until all factors i +# are eliminated. Stop the loop when n=1, i.e. all factors have +# been found. while n > 1: if primes[i] == 1 and n % i == 0: count = count + 1 @@ -40,8 +59,10 @@ def main(): primes = sieve(N) found = 0 - i = 645 + i = 647 +# Starting from 647, count the distinct prime factors of n, n+1, n+2 and n+3. +# If they all have 4, the solution is found. while not found and i < N - 3: if primes[i] == 0 and primes[i+1] == 0 and primes[i+2] == 0 and primes[i+3] == 0: if count_distinct_factors(i) == 4 and count_distinct_factors(i+1) == 4 and count_distinct_factors(i+2) == 4 and count_distinct_factors(i+3) == 4: diff --git a/Python/p048.py b/Python/p048.py index 1664a20..c830a49 100644 --- a/Python/p048.py +++ b/Python/p048.py @@ -1,5 +1,9 @@ #!/usr/bin/python3 +# 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. + from timeit import default_timer def main(): @@ -7,6 +11,7 @@ def main(): sum_ = 0 +# Simply calculate the sum of the powers for i in range(1, 1001): power = i ** i sum_ = sum_ + power diff --git a/Python/p049.py b/Python/p049.py index 375efbf..71576bd 100644 --- a/Python/p049.py +++ b/Python/p049.py @@ -1,5 +1,13 @@ #!/usr/bin/python3 +# The arithmetic sequence, 1487, 4817, 8147, in which each of the terms increases by 3330, is unusual in two ways: (i) each of the three terms are prime, +# and, (ii) each of the 4-digit numbers are permutations of one another. +# +# There are no arithmetic sequences made up of three 1-, 2-, or 3-digit primes, exhibiting this property, but there is one other 4-digit +# increasing sequence. +# +# What 12-digit number do you form by concatenating the three terms in this sequence? + from numpy import zeros from timeit import default_timer @@ -33,19 +41,27 @@ def main(): found = 0 i = 1489 - while i < N and found == 0: +# Starting from i=1489 (bigger than the first number in the sequence given in the problem), +# check odd numbers. If they're prime, loop on even numbers j (odd+even=odd, odd+odd=even and +# we need odd numbers because we're looking for primes) up to 4254 (1489+2*4256=10001 which has +# 5 digits. + while i < N: if primes[i] == 1: for j in range(1, 4255): +# If i, i+j and i+2*j are all primes and they have +# all the same digits, the result has been found. if i + 2 * j < N and primes[i+j] == 1 and primes[i+2*j] == 1 and\ check_digits(i, i+j) and check_digits(i, i+2*j): found = 1 break - i = i + 1 + if(found): + break + i = i + 2 end = default_timer() print('Project Euler, Problem 49') - print('Answer: {}'.format(str(i-1)+str(i-1+j)+str(i-1+2*j))) + print('Answer: {}'.format(str(i)+str(i+j)+str(i+2*j))) print('Elapsed time: {:.9f} seconds'.format(end - start)) diff --git a/Python/p050.py b/Python/p050.py index a67df71..ca828ab 100644 --- a/Python/p050.py +++ b/Python/p050.py @@ -1,5 +1,15 @@ #!/usr/bin/python3 +# The prime 41, can be written as the sum of six consecutive primes: +# +# 41 = 2 + 3 + 5 + 7 + 11 + 13 +# +# This is the longest sum of consecutive primes that adds to a prime below one-hundred. +# +# The longest sum of consecutive primes below one-thousand that adds to a prime, contains 21 terms, and is equal to 953. +# +# Which prime, below one-million, can be written as the sum of the most consecutive primes? + from timeit import default_timer from projecteuler import sieve @@ -13,11 +23,32 @@ def main(): max_ = 0 max_p = 0 - for i in range(2, N): +# Starting from a prime i, add consecutive primes until the +# sum exceeds the limit, every time the sum is also a prime +# save the value and the count if the count is larger than the +# current maximum. Repeat for all primes below N. +# A separate loop is used for i=2, so later only odd numbers are +# checked for primality. + i = 2 + j = i + 1 + count = 1 + sum_ = i + + while j < N and sum_ < N: + if primes[j] == 1: + sum_ = sum_ + j + count = count + 1 + + if sum_ < N and primes[sum_] == 1 and count > max_: + max_ = count + max_p = sum + j = j + 1 + + for i in range(3, N, 2): if primes[i] == 1: count = 1 sum_ = i - j = i + 1 + j = i + 2 while j < N and sum_ < N: if primes[j] == 1: @@ -28,7 +59,7 @@ def main(): max_ = count max_p = sum_ - j = j + 1 + j = j + 2 end = default_timer()