Add more solutions and minor corrections

Added solutions for problem 71, 72, 73, 74 and 75 in C and python
and made a few corrections in the code for other problems.
This commit is contained in:
2019-09-29 19:38:39 +02:00
parent 2cdbca922a
commit 7c055b749e
21 changed files with 962 additions and 6 deletions

View File

@ -10,8 +10,9 @@
#
# If the product of these four fractions is given in its lowest common terms, find the value of the denominator.
from math import gcd
from timeit import default_timer
from projecteuler import gcd
def main():
start = default_timer()

54
Python/p071.py Normal file
View File

@ -0,0 +1,54 @@
#!/usr/bin/python3
# Consider the fraction, n/d, where n and d are positive integers. If n<d and HCF(n,d)=1, it is called a reduced proper fraction.
#
# If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:
#
# 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8
#
# It can be seen that 2/5 is the fraction immediately to the left of 3/7.
#
# By listing the set of reduced proper fractions for d ≤ 1,000,000 in ascending order of size, find the numerator
# of the fraction immediately to the left of 3/7.
from math import gcd
from timeit import default_timer
def main():
start = default_timer()
N = 1000000
max_ = 0
# 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:
# pb<aq
# pb<=aq-1
# p<=(aq-1)/b
# So we can set p=(3*q-1)/7 (using integer division).
for i in range(2, N+1):
j = (3 * i - 1) // 7
if j / i > max_:
n = j
d = i
max_ = n / d
# Reduce the fractions if it's not already reduced.
if gcd(i, j) > 1:
n /= gcd(i, j)
d /= gcd(i, j)
max_n = n
end = default_timer()
print('Project Euler, Problem 71')
print('Answer: {}'.format(max_n))
print('Elapsed time: {:.9f} seconds'.format(end - start))
if __name__ == '__main__':
main()

39
Python/p072.py Normal file
View File

@ -0,0 +1,39 @@
#!/usr/bin/python3
# Consider the fraction, n/d, where n and d are positive integers. If n<d and HCF(n,d)=1, it is called a reduced proper fraction.
#
# If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:
#
# 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8
#
# It can be seen that there are 21 elements in this set.
#
# 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
def main():
start = default_timer()
N = 1000001
count = 0
primes = sieve(N)
# 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
# of Euler's Totient Function phi. It's sufficient to calculate phi for each
# denominator and sum the value.
for i in range(2, N):
count = count + phi(i, primes)
end = default_timer()
print('Project Euler, Problem 72')
print('Answer: {}'.format(count))
print('Elapsed time: {:.9f} seconds'.format(end - start))
if __name__ == '__main__':
main()

41
Python/p073.py Normal file
View File

@ -0,0 +1,41 @@
#!/usr/bin/python3
# Consider the fraction, n/d, where n and d are positive integers. If n<d and HCF(n,d)=1, it is called a reduced proper fraction.
#
# If we list the set of reduced proper fractions for d ≤ 8 in ascending order of size, we get:
#
# 1/8, 1/7, 1/6, 1/5, 1/4, 2/7, 1/3, 3/8, 2/5, 3/7, 1/2, 4/7, 3/5, 5/8, 2/3, 5/7, 3/4, 4/5, 5/6, 6/7, 7/8
#
# It can be seen that there are 3 fractions between 1/3 and 1/2.
#
# 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 timeit import default_timer
def main():
start = default_timer()
count = 0
# 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
# 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):
limit = (i - 1) // 2 + 1
for j in range(i//3+1, limit):
# Increment the counter if the current fraction is reduced.*/
if gcd(j, i) == 1:
count = count + 1
end = default_timer()
print('Project Euler, Problem 73')
print('Answer: {}'.format(count))
print('Elapsed time: {:.9f} seconds'.format(end - start))
if __name__ == '__main__':
main()

97
Python/p074.py Normal file
View File

@ -0,0 +1,97 @@
#!/usr/bin/python3
# The number 145 is well known for the property that the sum of the factorial of its digits is equal to 145:
#
# 1! + 4! + 5! = 1 + 24 + 120 = 145
#
# Perhaps less well known is 169, in that it produces the longest chain of numbers that link back to 169; it turns out that there are
# only three such loops that exist:
#
# 169 → 363601 → 1454 → 169
# 871 → 45361 → 871
# 872 → 45362 → 872
#
# It is not difficult to prove that EVERY starting number will eventually get stuck in a loop. For example,
#
# 69 → 363600 → 1454 → 169 → 363601 (→ 1454)
# 78 → 45360 → 871 → 45361 (→ 871)
# 540 → 145 (→ 145)
#
# Starting with 69 produces a chain of five non-repeating terms, but the longest non-repeating chain with a starting number
# below one million is sixty terms.
#
# How many chains, with a starting number below one million, contain exactly sixty non-repeating terms?
from math import factorial
from timeit import default_timer
def len_chain(n):
global N
global chains
chain = [0] * 60
count = 0
finished = 0
value = n
chain[count] = value
while not finished:
tmp = 0
count = count + 1
# Generate the next number of the chain by taking
# the digits of the current value, calculating the
# factorials and adding them.*/
while value != 0:
tmp = tmp + factorial(value % 10)
value = value // 10
# If the chain length for the new value has already been
# calculated before, use the saved value (only chains for
# values smaller than N are saved).*/
if tmp < N and chains[tmp] != 0:
return count + chains[tmp]
value = tmp
# If the current value is already present in the chain,
# the chain is finished.*/
for i in range(count):
if chain[i] == value:
finished = 1
chain[count] = value
chains[n] = count
return count
def main():
start = default_timer()
global N
global chains
N = 1000000
chains = [0] * N
count = 0
# Simple brute force approach, for every number calculate
# the length of the chain.
for i in range(3, N):
if len_chain(i) == 60:
count = count + 1
end = default_timer()
print('Project Euler, Problem 74')
print('Answer: {}'.format(count))
print('Elapsed time: {:.9f} seconds'.format(end - start))
if __name__ == '__main__':
main()

80
Python/p075.py Normal file
View File

@ -0,0 +1,80 @@
#!/usr/bin/python3
# It turns out that 12 cm is the smallest length of wire that can be bent to form an integer sided right angle triangle in exactly one way,
# but there are many more examples.
#
# 12 cm: (3,4,5)
# 24 cm: (6,8,10)
# 30 cm: (5,12,13)
# 36 cm: (9,12,15)
# 40 cm: (8,15,17)
# 48 cm: (12,16,20)
#
# In contrast, some lengths of wire, like 20 cm, cannot be bent to form an integer sided right angle triangle, and other lengths allow
# more than one solution to be found; for example, using 120 cm it is possible to form exactly three different integer sided right angle triangles.
#
# 120 cm: (30,40,50), (20,48,52), (24,45,51)
#
# 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 timeit import default_timer
def main():
start = default_timer()
N = 1500000
l = [0] * (N+1)
# Generate all Pythagorean triplets using Euclid's algorithm:
# For m>=2 and n<m:
# a=m*m-n*n
# b=2*m*n
# c=m*m+n*n
# 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
# 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
# when m=866 even with the smaller n (i.e. 1) the perimeter is greater
# than the given limit.
for m in range(2, 866):
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)):
a = m * m - n * n
b = 2 * m * n
c = m * m + n * n
if(a + b + c <= N):
l[a+b+c] = l[a+b+c] + 1
i = 2
tmpa = i * a
tmpb = i * b
tmpc = i * c
while(tmpa + tmpb + tmpc <= N):
l[tmpa+tmpb+tmpc] = l[tmpa+tmpb+tmpc] + 1
i = i + 1
tmpa = i * a
tmpb = i * b
tmpc = i * c
count = 0
for i in range(N+1):
if l[i] == 1:
count = count + 1
end = default_timer()
print('Project Euler, Problem 75')
print('Answer: {}'.format(count))
print('Elapsed time: {:.9f} seconds'.format(end - start))
if __name__ == '__main__':
main()

View File

@ -324,3 +324,76 @@ def phi_semiprime(n, p, q):
return n - p
else:
return n - (p + q) + 1
def phi(n, primes):
# If n is primes, phi(n)=n-1.
if primes[n] == 1:
return n - 1
# If n is semiprime, use above function.
semi_p, p, q = is_semiprime(n, primes)
if semi_p:
return phi_semiprime(n, p, q)
ph = n
# If 2 is a factor of n, multiply the current ph (which now is n)
# by 1-1/2, then divide all factors 2.
if n % 2 == 0:
ph = ph * (1 - 1 / 2)
while True:
n = n // 2
if n % 2 != 0:
break
# If 3 is a factor of n, multiply the current ph by 1-1/3,
# then divide all factors 3.
if n % 3 == 0:
ph = ph * (1 - 1 / 3)
while True:
n = n // 3
if n % 3 != 0:
break
# Any number can have only one prime factor greater than its
# square root, so we can stop checking at this point and deal
# with the only factor larger than sqrt(n), if present, at the end
limit = floor(sqrt(n)) + 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. For each of these possible primes, check if
# they are prime, then check if the number divides n, in which
# case update the current ph.
for i in range(5, limit, 6):
if primes[i]:
if n % i == 0:
ph = ph * (1 - 1 / i)
while True:
n = n // i
if n % i != 0:
break
if primes[i+2]:
if n % (i + 2) == 0:
ph = ph * (1 - 1 / (i + 2))
while True:
n = n // (i + 2)
if n % (i + 2) != 0:
break
# After dividing all prime factors smaller than sqrt(n), n is either 1
# or is equal to the only prime factor greater than sqrt(n). In this
# second case, we need to update ph with the last prime factor.
if n > 1:
ph = ph * (1 - 1 / n)
return ph