Use timing decorator for problems 71-80

This commit is contained in:
daniele 2023-06-07 20:39:55 +02:00
parent f54083389b
commit e8098ed5e5
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
10 changed files with 103 additions and 161 deletions

View File

@ -12,22 +12,22 @@
# of the fraction immediately to the left of 3/7. # of the fraction immediately to the left of 3/7.
from math import gcd from math import gcd
from timeit import default_timer
from projecteuler import timing
def main(): @timing
start = default_timer() def p071():
N = 1000000 N = 1000000
max_ = 0 max_ = 0
# For each denominator q, we need to find the biggest numerator p for which # For each denominator q, we need to find the biggest numerator p for which
# p/q<a/b, where a/b is 3/7 for this problem. So: # p/q<a/b, where a/b is 3/7 for this problem. So:
# pb<aq # pb<aq
# pb<=aq-1 # pb<=aq-1
# p<=(aq-1)/b # p<=(aq-1)/b
# So we can set p=(3*q-1)/7 (using integer division). # So we can set p=(3*q-1)/7 (using integer division).
for i in range(2, N+1): for i in range(2, N+1):
j = (3 * i - 1) // 7 j = (3 * i - 1) // 7
@ -36,20 +36,16 @@ def main():
d = i d = i
max_ = n / d max_ = n / d
# Reduce the fractions if it's not already reduced. # Reduce the fractions if it's not already reduced.
if gcd(i, j) > 1: if gcd(i, j) > 1:
n /= gcd(i, j) n /= gcd(i, j)
d /= gcd(i, j) d /= gcd(i, j)
max_n = n max_n = n
end = default_timer()
print('Project Euler, Problem 71') print('Project Euler, Problem 71')
print(f'Answer: {max_n}') print(f'Answer: {max_n}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p071()

View File

@ -10,33 +10,26 @@
# #
# How many elements would be contained in the set of reduced proper fractions for d ≤ 1,000,000? # How many elements would be contained in the set of reduced proper fractions for d ≤ 1,000,000?
from timeit import default_timer from projecteuler import sieve, phi, timing
from projecteuler import sieve, phi
def main(): @timing
start = default_timer() def p072():
N = 1000001 N = 1000001
count = 0 count = 0
primes = sieve(N) primes = sieve(N)
# For any denominator d, the number of reduced proper fractions is # For any denominator d, the number of reduced proper fractions is
# the number of fractions n/d where gcd(n, d)=1, which is the definition # the number of fractions n/d where gcd(n, d)=1, which is the definition
# of Euler's Totient Function phi. It's sufficient to calculate phi for each # of Euler's Totient Function phi. It's sufficient to calculate phi for each
# denominator and sum the value. # denominator and sum the value.
for i in range(2, N): for i in range(2, N):
count = count + phi(i, primes) count = count + phi(i, primes)
end = default_timer()
print('Project Euler, Problem 72') print('Project Euler, Problem 72')
print(f'Answer: {count}') print(f'Answer: {int(count)}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p072()

View File

@ -11,32 +11,28 @@
# How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000? # How many fractions lie between 1/3 and 1/2 in the sorted set of reduced proper fractions for d ≤ 12,000?
from math import gcd from math import gcd
from timeit import default_timer
from projecteuler import timing
def main(): @timing
start = default_timer() def p073():
count = 0 count = 0
# For each denominator q, we need to find the fractions p/q for which # For each denominator q, we need to find the fractions p/q for which
# 1/3<p/q<1/2. For the lower limit, if p=q/3, then p/q=1/3, so we take # 1/3<p/q<1/2. For the lower limit, if p=q/3, then p/q=1/3, so we take
# p=q/3+1. For the upper limit, if p=q/2 p/q=1/2, so we take p=(q-1)/2. # p=q/3+1. For the upper limit, if p=q/2 p/q=1/2, so we take p=(q-1)/2.
for i in range(2, 12001): for i in range(2, 12001):
limit = (i - 1) // 2 + 1 limit = (i - 1) // 2 + 1
for j in range(i//3+1, limit): for j in range(i//3+1, limit):
# Increment the counter if the current fraction is reduced.*/ # Increment the counter if the current fraction is reduced.*/
if gcd(j, i) == 1: if gcd(j, i) == 1:
count = count + 1 count = count + 1
end = default_timer()
print('Project Euler, Problem 73') print('Project Euler, Problem 73')
print(f'Answer: {count}') print(f'Answer: {count}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p073()

View File

@ -23,7 +23,8 @@
# How many chains, with a starting number below one million, contain exactly sixty non-repeating terms? # How many chains, with a starting number below one million, contain exactly sixty non-repeating terms?
from math import factorial from math import factorial
from timeit import default_timer
from projecteuler import timing
N = 1000000 N = 1000000
@ -42,23 +43,23 @@ def len_chain(n):
tmp = 0 tmp = 0
count = count + 1 count = count + 1
# Generate the next number of the chain by taking # Generate the next number of the chain by taking
# the digits of the current value, calculating the # the digits of the current value, calculating the
# factorials and adding them.*/ # factorials and adding them.
while value != 0: while value != 0:
tmp = tmp + factorial(value % 10) tmp = tmp + factorial(value % 10)
value = value // 10 value = value // 10
# If the chain length for the new value has already been # If the chain length for the new value has already been
# calculated before, use the saved value (only chains for # calculated before, use the saved value (only chains for
# values smaller than N are saved).*/ # values smaller than N are saved).
if tmp < N and chains[tmp] != 0: if tmp < N and chains[tmp] != 0:
return count + chains[tmp] return count + chains[tmp]
value = tmp value = tmp
# If the current value is already present in the chain, # If the current value is already present in the chain,
# the chain is finished.*/ # the chain is finished.
for i in range(count): for i in range(count):
if chain[i] == value: if chain[i] == value:
finished = 1 finished = 1
@ -70,24 +71,19 @@ def len_chain(n):
return count return count
def main(): @timing
start = default_timer() def p074():
count = 0 count = 0
# Simple brute force approach, for every number calculate # Simple brute force approach, for every number calculate
# the length of the chain. # the length of the chain.
for i in range(3, N): for i in range(3, N):
if len_chain(i) == 60: if len_chain(i) == 60:
count = count + 1 count = count + 1
end = default_timer()
print('Project Euler, Problem 74') print('Project Euler, Problem 74')
print(f'Answer: {count}') print(f'Answer: {count}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p074()

View File

@ -18,27 +18,27 @@
# Given that L is the length of the wire, for how many values of L ≤ 1,500,000 can exactly one integer sided right angle triangle be formed? # Given that L is the length of the wire, for how many values of L ≤ 1,500,000 can exactly one integer sided right angle triangle be formed?
from math import gcd from math import gcd
from timeit import default_timer
from projecteuler import timing
def main(): @timing
start = default_timer() def p075():
N = 1500000 N = 1500000
l = [0] * (N+1) l = [0] * (N+1)
# Generate all Pythagorean triplets using Euclid's algorithm: # Generate all Pythagorean triplets using Euclid's algorithm:
# For m>=2 and n<m: # For m>=2 and n<m:
# a=m*m-n*n # a=m*m-n*n
# b=2*m*n # b=2*m*n
# c=m*m+n*n # c=m*m+n*n
# This gives a primitive triple if gcd(m, n)=1 and exactly one # This gives a primitive triple if gcd(m, n)=1 and exactly one
# of m and n is odd. To generate all the triples, generate all # of m and n is odd. To generate all the triples, generate all
# the primitive one and multiply them by i=2,3, ..., n until the # the primitive one and multiply them by i=2,3, ..., n until the
# perimeter is larger than the limit. The limit for m is 865, because # perimeter is larger than the limit. The limit for m is 865, because
# when m=866 even with the smaller n (i.e. 1) the perimeter is greater # when m=866 even with the smaller n (i.e. 1) the perimeter is greater
# than the given limit. # than the given limit.
for m in range(2, 866): for m in range(2, 866):
for n in range(1, m): for n in range(1, m):
if gcd(m, n) == 1 and ((m % 2 == 0 and n % 2 != 0) or (m % 2 != 0 and n % 2 == 0)): if gcd(m, n) == 1 and ((m % 2 == 0 and n % 2 != 0) or (m % 2 != 0 and n % 2 == 0)):
@ -68,13 +68,9 @@ def main():
if l[i] == 1: if l[i] == 1:
count = count + 1 count = count + 1
end = default_timer()
print('Project Euler, Problem 75') print('Project Euler, Problem 75')
print(f'Answer: {count}') print(f'Answer: {count}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p075()

View File

@ -11,28 +11,21 @@
# #
# How many different ways can one hundred be written as a sum of at least two positive integers?*/ # How many different ways can one hundred be written as a sum of at least two positive integers?*/
from timeit import default_timer from projecteuler import partition_fn, timing
from projecteuler import partition_fn
def main(): @timing
start = default_timer() def p076():
partitions = [0] * 101 partitions = [0] * 101
# The number of ways a number can be written as a sum is given by the partition function # The number of ways a number can be written as a sum is given by the partition function
# (-1 because the partition function includes also the number itself). # (-1 because the partition function includes also the number itself).
# The function is implemented in projecteuler.py. # The function is implemented in projecteuler.py.
n = partition_fn(100, partitions) - 1 n = partition_fn(100, partitions) - 1
end = default_timer()
print('Project Euler, Problem 76') print('Project Euler, Problem 76')
print(f'Answer: {n}') print(f'Answer: {n}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p076()

View File

@ -10,16 +10,13 @@
# #
# What is the first value which can be written as the sum of primes in over five thousand different ways? # What is the first value which can be written as the sum of primes in over five thousand different ways?
from timeit import default_timer from projecteuler import is_prime, timing
from projecteuler import is_prime
primes = [0] * 100 primes = [0] * 100
# Function using a simple recursive brute force approach # Function using a simple recursive brute force approach to find all the partitions.
# to find all the partitions.
def count(value, n, i, target): def count(value, n, i, target):
for j in range(i, 100): for j in range(i, 100):
value = value + primes[j] value = value + primes[j]
@ -36,10 +33,9 @@ def count(value, n, i, target):
return n return n
def main(): @timing
start = default_timer() def p077():
# Generate a list of the first 100 primes.
# Generate a list of the first 100 primes.
i = 0 i = 0
j = 0 j = 0
@ -51,9 +47,9 @@ def main():
i = 2 i = 2
# Use a function to count the number of prime partitions for # Use a function to count the number of prime partitions for
# each number >= 2 until the one that can be written in over # each number >= 2 until the one that can be written in over
# 5000 ways is found. # 5000 ways is found.
while True: while True:
n = count(0, 0, 0, i) n = count(0, 0, 0, i)
@ -62,13 +58,9 @@ def main():
i = i + 1 i = i + 1
end = default_timer()
print('Project Euler, Problem 77') print('Project Euler, Problem 77')
print(f'Answer: {i}') print(f'Answer: {i}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p077()

View File

@ -13,32 +13,24 @@
# #
# Find the least value of n for which p(n) is divisible by one million. # Find the least value of n for which p(n) is divisible by one million.
from timeit import default_timer from projecteuler import partition_fn, timing
from projecteuler import partition_fn
def main(): @timing
start = default_timer() def p078():
N = 1000000 N = 1000000
partitions = [0] * N partitions = [0] * N
i = 0 i = 0
# Using the partition function to calculate the number of partitions, # Using the partition function to calculate the number of partitions, giving the result modulo N.
# giving the result modulo N.*/
while partition_fn(i, partitions, N) != 0: while partition_fn(i, partitions, N) != 0:
i = i + 1 i = i + 1
end = default_timer()
print('Project Euler, Problem 78') print('Project Euler, Problem 78')
print(f'Answer: {i}') print(f'Answer: {i}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p078()

View File

@ -10,13 +10,13 @@
import sys import sys
from itertools import permutations from itertools import permutations
from timeit import default_timer
from projecteuler import timing
def check_passcode(passcode, len_, logins, n): def check_passcode(passcode, len_, logins, n):
# For every login attempt, check if all the digits appear in the # For every login attempt, check if all the digits appear in the passcode in the correct order. Return 0 if a login attempt
# passcode in the correct order. Return 0 if a login attempt # incompatible with the current passcode is found.
# incompatible with the current passcode is found.
for i in range(n): for i in range(n):
k = 0 k = 0
for j in range(len_): for j in range(len_):
@ -32,9 +32,8 @@ def check_passcode(passcode, len_, logins, n):
return 1 return 1
def main(): @timing
start = default_timer() def p079():
try: try:
with open('p079_keylog.txt', 'r', encoding='utf-8') as fp: with open('p079_keylog.txt', 'r', encoding='utf-8') as fp:
logins = fp.readlines() logins = fp.readlines()
@ -48,7 +47,7 @@ def main():
for i in logins: for i in logins:
keylog = int(i) keylog = int(i)
# Check which digits are present in the login attempts. # Check which digits are present in the login attempts.
while True: while True:
digits[keylog % 10] = digits[keylog % 10] + 1 digits[keylog % 10] = digits[keylog % 10] + 1
keylog = keylog // 10 keylog = keylog // 10
@ -58,8 +57,7 @@ def main():
j = 0 j = 0
for i in range(10): for i in range(10):
# To generate the passcode, only use the digits present in the # To generate the passcode, only use the digits present in the login attempts.
# login attempts.
if digits[i] > 0: if digits[i] > 0:
passcode_digits[j] = i passcode_digits[j] = i
j = j + 1 j = j + 1
@ -70,18 +68,17 @@ def main():
while not found: while not found:
passcode = [0] * len_ passcode = [0] * len_
# For the current length, generate the first passcode with the # For the current length, generate the first passcode with the digits in order.
# digits in order.
for i in range(len_): for i in range(len_):
passcode[i] = passcode_digits[i] passcode[i] = passcode_digits[i]
# Check if the passcode is compatible with the login attempts. # Check if the passcode is compatible with the login attempts.
if check_passcode(passcode, len_, logins, 50): if check_passcode(passcode, len_, logins, 50):
found = 1 found = 1
break break
# For the given length, check every permutation until the correct # For the given length, check every permutation until the correct
# passcode has been found, or all the permutations have been tried. # passcode has been found, or all the permutations have been tried.
passcodes = permutations(passcode, len_) passcodes = permutations(passcode, len_)
for i in passcodes: for i in passcodes:
@ -90,16 +87,12 @@ def main():
res = ''.join(map(str, i)) res = ''.join(map(str, i))
break break
# If the passcode has not yet been found, try a longer passcode. # If the passcode has not yet been found, try a longer passcode.
len_ = len_ + 1 len_ = len_ + 1
end = default_timer()
print('Project Euler, Problem 79') print('Project Euler, Problem 79')
print(f'Answer: {res}') print(f'Answer: {res}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p079()

View File

@ -8,9 +8,10 @@
# For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits # For the first one hundred natural numbers, find the total of the digital sums of the first one hundred decimal digits
# for all the irrational square roots # for all the irrational square roots
from timeit import default_timer
from mpmath import sqrt, mp from mpmath import sqrt, mp
from projecteuler import timing
def is_square(n): def is_square(n):
p = sqrt(n) p = sqrt(n)
@ -19,18 +20,16 @@ def is_square(n):
return bool(p == m) return bool(p == m)
def main(): @timing
start = default_timer() def p080():
# Set the precision to 100 digits
# Set the precision to 100 digits
mp.dps = 102 mp.dps = 102
sum_ = 0 sum_ = 0
for i in range(2, 100): for i in range(2, 100):
if not is_square(i): if not is_square(i):
# Calculate the square root of the current number with the given precision # Calculate the square root of the current number with the given precision and sum the digits to the total.
# and sum the digits to the total.
root = str(sqrt(i)) root = str(sqrt(i))
sum_ = sum_ + int(root[0]) sum_ = sum_ + int(root[0])
@ -38,13 +37,9 @@ def main():
for j in range(2, 101): for j in range(2, 101):
sum_ = sum_ + int(root[j]) sum_ = sum_ + int(root[j])
end = default_timer()
print('Project Euler, Problem 80') print('Project Euler, Problem 80')
print(f'Answer: {sum_}') print(f'Answer: {sum_}')
print(f'Elapsed time: {end - start:.9f} seconds')
if __name__ == '__main__': if __name__ == '__main__':
main() p080()