Use timing decorator for problems 11-20

This commit is contained in:
daniele 2023-06-07 17:55:56 +02:00
parent 885084211a
commit 634eb3f750
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
10 changed files with 85 additions and 130 deletions

View File

@ -27,12 +27,11 @@
#
# 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 projecteuler import timing
def main():
start = default_timer()
@timing
def p011():
grid = [[8, 2, 22, 97, 38, 15, 0, 40, 0, 75, 4, 5, 7, 78, 52, 12, 50, 77, 91, 8],
[49, 49, 99, 40, 17, 81, 18, 57, 60, 87, 17, 40, 98, 43, 69, 48, 4, 56, 62, 0],
[81, 49, 31, 73, 55, 79, 14, 29, 93, 71, 40, 67, 53, 88, 30, 3, 49, 13, 36, 65],
@ -56,12 +55,12 @@ 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.
# 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.
# Horizontal direction.
prod = 1
k = j
while k < j + 4:
@ -71,7 +70,7 @@ def main():
if prod > max_:
max_ = prod
# Vertical direction.
# Vertical direction.
prod = 1
k = i
while k < i + 4:
@ -81,7 +80,7 @@ def main():
if prod > max_:
max_ = prod
# Diagonal direction, from top left to bottom right.
# Diagonal direction, from top left to bottom right.
prod = 1
k = i
w = j
@ -94,10 +93,10 @@ def main():
if prod > max_:
max_ = prod
# The last diagonal is handled separately
# 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.
# Diagonal direction, from top right to bottom left.
prod = 1
k = i
w = j
@ -110,13 +109,9 @@ def main():
if prod > max_:
max_ = prod
end = default_timer()
print('Project Euler, Problem 11')
print(f'Answer: {max_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p011()

View File

@ -19,33 +19,27 @@
#
# 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
from projecteuler import count_divisors, timing
def main():
start = default_timer()
@timing
def p012():
i = 0
triang = 0
finished = 0
# Generate all triangle numbers until the first one with more than 500 divisors is found.
# 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.
# Use the function implemented in projecteuler.py to count divisors of a number.
if count_divisors(triang) > 500:
finished = 1
end = default_timer()
print('Project Euler, Problem 12')
print(f'Answer: {triang}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p012()

View File

@ -103,13 +103,13 @@
# 20849603980134001723930671666823555245252804609722
# 53503534226472524250874054075591789781264330331690
from timeit import default_timer
import numpy as np
from projecteuler import timing
def main():
start = default_timer()
@timing
def p013():
numbers = [37107287533902102798797998220837590246510135740250,
46376937677490009712648124896970078050417018260538,
74324986199524741059474233309513058123726617309629,
@ -211,18 +211,14 @@ def main():
20849603980134001723930671666823555245252804609722,
53503534226472524250874054075591789781264330331690]
# Convert the list of numbers in a numpy array and calculate the sum
# Convert the list of numbers in a numpy array and calculate the sum
numbers = np.array(numbers)
sum_ = str(numbers.sum())
end = default_timer()
print('Project Euler, Problem 13')
print(f'Answer: {sum_[:10]}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p013()

View File

@ -16,9 +16,10 @@
#
# NOTE: Once the chain starts the terms are allowed to go above one million.
from timeit import default_timer
from numpy import zeros
from projecteuler import timing
N = 1000000
collatz_found = zeros(N, dtype=int)
@ -32,8 +33,8 @@ def collatz_length(n):
if n == 1:
return 1
# If Collatz(n) has been previously calculated,
# just return the value.
# If Collatz(n) has been previously calculated,
# just return the value.
if n < N and collatz_found[n]:
return collatz_found[n]
@ -42,14 +43,14 @@ def collatz_length(n):
return 1 + collatz_length(3*n+1)
def main():
start = default_timer()
@timing
def p014():
max_l = 0
max_ = 0
# 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 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
@ -58,13 +59,9 @@ def main():
max_l = count
max_ = i
end = default_timer()
print('Project Euler, Problem 14')
print(f'Answer: {max_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p014()

View File

@ -4,28 +4,24 @@
# How many such routes are there through a 20×20 grid?
from math import factorial
from timeit import default_timer
from projecteuler import timing
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.
@timing
def p015():
# 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
count = count // tmp
end = default_timer()
print('Project Euler, Problem 15')
print(f'Answer: {count}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p015()

View File

@ -4,14 +4,13 @@
#
# What is the sum of the digits of the number 2^1000?
from timeit import default_timer
from projecteuler import timing
def main():
start = default_timer()
# Simply calculate 2^1000, convert the result to string and calculate
# the sum of the digits
@timing
def p016():
# Simply calculate 2^1000, convert the result to string and calculate
# the sum of the digits
res = str(2 ** 1000)
sum_ = 0
@ -19,13 +18,9 @@ def main():
for i in res:
sum_ = sum_ + int(i)
end = default_timer()
print('Project Euler, Problem 16')
print(f'Answer: {sum_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p016()

View File

@ -7,16 +7,15 @@
# 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 projecteuler import timing
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
@timing
def p017():
# 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],
[6, 6, 5, 5, 5, 7, 6, 6],
[13, 13, 15, 14, 14, 13, 15, 15, 14],
@ -24,46 +23,43 @@ def main():
sum_ = 0
# Sum the letters of the first 19 numbers.
# 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.
# 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").
# "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".
# 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.
# 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.
# "One hundred and", "two hundred and",... are used 100 times each.
n_letters[2][i] = n_letters[2][i] * 100
# Add "one" to "nineteen".
# 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.
# 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.
# "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".
# Add "one thousand".
sum_ = sum_ + n_letters[3][0]
end = default_timer()
print('Project Euler, Problem 17')
print(f'Answer: {sum_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p017()

View File

@ -31,14 +31,12 @@
# with a triangle containing one-hundred rows; it cannot be solved by brute force, and requires a clever method! ;o)
import sys
from timeit import default_timer
from projecteuler import find_max_path
from projecteuler import find_max_path, timing
def main():
start = default_timer()
@timing
def p018():
try:
with open('p018_triangle.txt', 'r', encoding='utf-8') as fp:
triang = []
@ -54,16 +52,12 @@ def main():
for i in range(l):
triang[i] = list(map(int, triang[i]))
# Use the function implemented in projecteuler.c to find the maximum path.
# Use the function implemented in projecteuler.c to find the maximum path.
max_ = find_max_path(triang, 15)
end = default_timer()
print('Project Euler, Problem 18')
print(f'Answer: {max_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p018()

View File

@ -14,27 +14,23 @@
# 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
from projecteuler import timing
def main():
start = default_timer()
@timing
def p019():
count = 0
# Use the datetime library to find out which first day of the month is a Sunday
# 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:
count = count + 1
end = default_timer()
print('Project Euler, Problem 19')
print(f'Answer: {count}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p019()

View File

@ -8,13 +8,13 @@
# Find the sum of the digits in the number 100!
from math import factorial
from timeit import default_timer
from projecteuler import timing
def main():
start = default_timer()
# Calculate the factorial, convert the result to string and sum the digits.
@timing
def p020():
# Calculate the factorial, convert the result to string and sum the digits.
n = str(factorial(100))
sum_ = 0
@ -22,13 +22,9 @@ def main():
for i in n:
sum_ = sum_ + int(i)
end = default_timer()
print('Project Euler, Problem 20')
print(f'Answer: {sum_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__':
main()
p020()