Add python solution for problems 85, 86, 87, 92, 95

This commit is contained in:
daniele 2023-06-07 23:02:57 +02:00
parent cc90c8aa0c
commit ce8b152bd7
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
7 changed files with 252 additions and 3 deletions

33
Python/p085.py Normal file
View File

@ -0,0 +1,33 @@
# By counting carefully it can be seen that a rectangular grid measuring 3 by 2 contains eighteen rectangles.
# Although there exists no rectangular grid that contains exactly two million rectangles, find the area of the grid with the nearest solution.
import sys
from projecteuler import timing
@timing
def p085():
N = 2000000
min_diff = sys.maxsize
for i in range(1, 100):
for j in range(1, i + 1):
# In a 2x3 grid, we can take rectangles of height 2 in 3 ways (two rectangles of heigh
# one and one of height 2). For the width, we can take 6 rectangles (3 of width 1,
# 2 of width 2 and 1 of width 3). The total is 6x3=18 rectangles.
# Extending to m x n, we can take (m+m-1+m-2+...+1)x(n+n-1+n-2+...+1)=
# m(m + 1) / 2 * n(n + 1) / 2 = m(m + 1) * n(n + 1) / 4 rectangles
n = (i * (i + 1) * j * (j + 1)) / 4
diff = abs(N - n)
if diff < min_diff:
min_diff = diff
area = i * j
print('Project Euler, Problem 85')
print(f'Answer: {area}')
if __name__ == '__main__':
p085()

39
Python/p086.py Normal file
View File

@ -0,0 +1,39 @@
# A spider, S, sits in one corner of a cuboid room, measuring 6 by 5 by 3, and a fly, F, sits in the opposite corner.
# By travelling on the surfaces of the room the shortest "straight line" distance from S to F is 10 and the path is shown on the diagram.
#
# However, there are up to three "shortest" path candidates for any given cuboid and the shortest route doesn't always have integer length.
#
# It can be shown that there are exactly 2060 distinct cuboids, ignoring rotations, with integer dimensions,
# up to a maximum size of M by M by M, for which the shortest route has integer length when M = 100.
# This is the least value of M for which the number of solutions first exceeds two thousand; the number of solutions when M = 99 is 1975.
#
# Find the least value of M such that the number of solutions first exceeds one million.
from math import sqrt
from projecteuler import timing
@timing
def p086():
N = 1000000
a = 0
count = 0
while count <= N:
a += 1
for b in range(1, a + 1):
for c in range(1, b + 1):
d = sqrt(a * a + (b + c) ** 2)
if d == int(d):
count += 1
print('Project Euler, Problem 86')
print(f'Answer: {a}')
if __name__ == '__main__':
p086()

44
Python/p087.py Normal file
View File

@ -0,0 +1,44 @@
# The smallest number expressible as the sum of a prime square, prime cube, and prime fourth power is 28. In fact,
# there are exactly four numbers below fifty that can be expressed in such a way:
#
# 28 = 22 + 23 + 24
# 33 = 32 + 23 + 24
# 49 = 52 + 23 + 24
# 47 = 22 + 33 + 24
#
# How many numbers below fifty million can be expressed as the sum of a prime square, prime cube, and prime fourth power?
from numpy import zeros
from projecteuler import sieve, timing
@timing
def p087():
N = 50000000
SQRT_N = 7071
RAD3_N = 368
RAD4_N = 84
primes = sieve(SQRT_N + 1)
numbers = zeros(N)
count = 0
for i in range(2, SQRT_N + 1):
if primes[i]:
for j in range(2, RAD3_N + 1):
if primes[j]:
for k in range(2, RAD4_N + 1):
if primes[k]:
n = i ** 2 + j ** 3 + k ** 4
if n < N and numbers[n] == 0:
count += 1
numbers[n] = 1
print('Project Euler, Problem 87')
print(f'Answer: {count}')
if __name__ == '__main__':
p087()

57
Python/p092.py Normal file
View File

@ -0,0 +1,57 @@
# A number chain is created by continuously adding the square of the digits in a number to form a new number until it has been seen before.
#
# For example,
#
# 44 → 32 → 13 → 10 → 1 → 1
# 85 → 89 → 145 → 42 → 20 → 4 → 16 → 37 → 58 → 89
#
# Therefore any chain that arrives at 1 or 89 will become stuck in an endless loop. What is most amazing is that
# EVERY starting number will eventually arrive at 1 or 89.
#
# How many starting numbers below ten million will arrive at 89?
from numpy import zeros
from projecteuler import timing
N = 10000000
chains = zeros(N)
def chain(n):
tmp = 0
if n == 1:
return 1
if n == 89:
return 89
if chains[n] != 0:
return chains[n]
while n > 0:
digit = n % 10
tmp += digit ** 2
n //= 10
return chain(tmp)
@timing
def p092():
count = 0
for i in range(1, N):
chains[i] = chain(i)
if chains[i] == 89:
count += 1
print('Project Euler, Problem 92')
print(f'Answer: {count}')
if __name__ == '__main__':
p092()

75
Python/p095.py Normal file
View File

@ -0,0 +1,75 @@
# The proper divisors of a number are all the divisors excluding the number itself. For example, the proper divisors
# of 28 are 1, 2, 4, 7, and 14. As the sum of these divisors is equal to 28, we call it a perfect number.
#
# Interestingly the sum of the proper divisors of 220 is 284 and the sum of the proper divisors of 284 is 220,
# forming a chain of two numbers. For this reason, 220 and 284 are called an amicable pair.
#
# Perhaps less well known are longer chains. For example, starting with 12496, we form a chain of five numbers:
#
# 12496 → 14288 → 15472 → 14536 → 14264 (→ 12496 → ...)
#
# Since this chain returns to its starting point, it is called an amicable chain.
#
# Find the smallest member of the longest amicable chain with no element exceeding one million.
from numpy import zeros
from projecteuler import sum_of_divisors, timing
N = 1000000
divisors = zeros(N + 1)
def sociable_chain(i, chain, l, min_):
chain[l] = i
if i == 1:
return -1
if divisors[i] != 0:
n = int(divisors[i])
else:
n = int(sum_of_divisors(i))
if n > N:
return -1
if n == chain[0]:
return l + 1
for j in range(l, 0, -1):
if n == chain[j]:
return -1
if n < min_:
min_ = n
return sociable_chain(n, chain, l + 1, min_)
@timing
def p095():
chain = zeros(N)
min_ = 0
l_max = 0
for i in range(4, N + 1):
divisors[i] = sum_of_divisors(i)
if divisors[i] == i:
continue
min_tmp = i
length = sociable_chain(i, chain, 0, min_tmp)
if length > l_max:
l_max = length
min_ = min_tmp
print('Project Euler, Problem 95')
print(f'Answer: {min_}')
if __name__ == '__main__':
p095()

View File

@ -146,7 +146,8 @@ def sum_of_divisors(n):
for i in range(2, limit):
if n % i == 0:
sum_ = sum_ + i
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

View File

@ -2,6 +2,6 @@
These are my solutions in C and Python, not necessarily the best solutions. I've solved most of the first 100 problems, currently working on cleaning the code and uploading it. I will try to solve more problems in the future.
# Notes
- Solutions for problems 82 and 145 in Python are really slow.
- Solutions for problems 84, 85, 86, 87, 89, 92, 95, 96, 97. 99, 102, 112, 124 and 357 have been implemented in C but not in Python.
- Solutions for problems 82, 86, 95, and 145 in Python are quite slow.
- Solutions for problems 84, 89, 96, 97. 99, 102, 112, 124 and 357 have been implemented in C but not in Python.
- Solutions for problems 88, 90 and 91 have been implemented in Python but not in C.