Add Python solutions for problems 88, 90, 91

This commit is contained in:
daniele 2023-06-07 17:36:45 +02:00
parent b46ae4e387
commit 955dc12737
Signed by: fuxino
GPG Key ID: 981A2B2A3BBF5514
4 changed files with 208 additions and 0 deletions

74
Python/p088.py Normal file
View File

@ -0,0 +1,74 @@
#!/usr/bin/env python3
# A natural number, N, hat can be written as the sum and product of a given set of at least two natural numbers, {a1,a2,...,ak} is called a product sum number: N = a1 + a2 + ... + ak = a1 x a2 x ... ak.
#
# For example, 6 = 1 + 2 + 3 = 1 x 2 x 3
#
# For a given set of size, k, we shall call the smallest N with this property a minimal product-sum number. The minimal product-sum numbers for sets of size, k = 2,3,4,5, and 6 are as follows.
#
# k = 2: 4 = 2 x 2 = 2 + 2
# k = 3: 6 = 1 x 2 x 3 = 1 + 2 + 3
# k = 4: 8 = 1 x 1 x 2 x 4 = 1 + 1 + 2 + 4
# k = 5: 8 = 1 x 1 x 2 x 2 x 2 = 1 + 1 + 2 + 2 + 2
# k = 6: 12 = 1 x 1 x 1 x 1 x 2 x 6 = 1 + 1 + 1 + 1 + 2 + 6
#
# Hence,for 2<=k<=6, the sum for all the minimal product-sum numbers is 4 + 6 + 8 + 12 = 30; note that 8 is only counted once in the sum.
#
# In fact, as the complete set of minimal product-sum numbers for 2<=k<=12 is {4,6,8,12,15,16}, the sum is 61.
#
# What is the sum of all the minimal product-sum numbers for 2<=k<=12000?
from math import floor, sqrt, prod
from projecteuler import sieve, timing
N = 12000
factorizations = {}
product_sums = {}
def factorize(n, factors, start, max_):
if n == 1:
factorizations[start].append(sorted(factors))
return
for i in range(max_, 1, -1):
if n % i == 0:
factors.append(i)
factorize(n // i, factors, start, i)
factors.pop()
@timing
def p088():
primes = sieve(2*N + 1)
for i in range(2, 2*N + 1):
if not primes[i]:
factorizations[i] = []
factorize(i, [], i, i)
for _, f in factorizations.items():
for i in f:
l = len(i) + (prod(i) - sum(i))
if l > N:
continue
if l not in product_sums:
product_sums[l] = prod(i)
elif prod(i) < product_sums[l]:
product_sums[l] = prod(i)
min_prod_sums = list(set(list(product_sums.values())))
res = sum(min_prod_sums)
print('Project Euler, Problem 88')
print(f'Answer: {res}')
if __name__ == '__main__':
p088()

82
Python/p090.py Normal file
View File

@ -0,0 +1,82 @@
#!/usr/bin/env python3
# Each of the six faces on a cube has a different digit (0 to 9) written on it; the same is done to a second cube. By placing the two cubes side-by-side in different positions we can form a variety of 2-digit numbers.
#
# For example, the square number 64 could be formed:
# |6||4|
#
# In fact, by carefully choosing the digits on both cubes it is possible to display all of the square numbers below one-hundred: 01, 04, 09, 16, 25, 36, 49, 64, and 81.
#
# For example, one way this can be achieved is by placing {0,5,6,7,8,9} on one cube and {1,2,3,4,8,9} on the other cube.
#
# However, for this problem we shall allow the 6 or 9 to be turned upside-down so that an arrangement like {0,5,6,7,8,9} and {1,2,3,4,6,7} allows for all nine square numbers to be displayed; otherwise it would be impossible to obtain 09.
#
# In determining a distinct arrangement we are interested in the digits on each cube, not the order.
#
# {1,2,3,4,5,6} is equivalent to {3,6,4,1,2,5}
# {1,2,3,4,5,6} is distinct from {1,2,3,4,5,9}
#
# But because we are allowing 6 and 9 to be reversed, the two distinct sets in the last example both represent the extended set {1,2,3,4,5,6,9} for the purpose of forming 2-digit numbers.
#
# How many distinct arrangements of the two cubes allow for all of the square numbers to be displayed?
from copy import copy
from itertools import product
from projecteuler import timing
N = 10
K = 6
COMBINATIONS = []
def combination(i, k, comb):
if len(comb) == K:
COMBINATIONS.append(copy(comb))
return
for j in range(i, N - k + 1):
comb.append(j)
combination(j + 1, k - 1, comb)
comb.pop()
@timing
def p090():
squares = [1, 4, 9, 16, 25, 36, 49, 64, 81]
combination(0, K, [])
for c in COMBINATIONS:
if 6 in c and 9 not in c:
c.append(9)
if 9 in c and 6 not in c:
c.append(6)
count = 0
for i, c in enumerate(COMBINATIONS):
for j in range(i + 1, len(COMBINATIONS)):
cur_squares = copy(squares)
prods = list(product(c, COMBINATIONS[j]))
prods.extend(list(product(COMBINATIONS[j], c)))
for elem in prods:
val = int(str(elem[0]) + str(elem[1]))
if val in cur_squares:
cur_squares.remove(val)
if len(cur_squares) == 0:
count += 1
break
print('Project Euler, Problem 90')
print(f'Answer: {count}')
if __name__ == '__main__':
p090()

51
Python/p091.py Normal file
View File

@ -0,0 +1,51 @@
#!/usr/bin/env python3
# The points P(x1,y1) and Q(x2,y2) are plotted at integer co-ordinates and are joined to the origin, O(0,0), to form ΔOPQ.
#
# There are exactly fourteen triangles containing a right angle that can be formed when each co-ordinate lies between 0 and 2 inclusive; that is, 0<=x1,y1,x2,y2<=2.
#
# Given that 0<=x1,y1,x2,y2<=50, how many right triangles can be formed?
from itertools import product
from projecteuler import timing
N = 50
def check_triangle(p1, p2, p3):
a = int((p2[0] - p1[0]) ** 2 + (p2[1] - p1[1]) ** 2)
b = int((p3[0] - p2[0]) ** 2 + (p3[1] - p2[1]) ** 2)
c = int((p3[0] - p1[0]) ** 2 + (p3[1] - p1[1]) ** 2)
if ((a > 0 and b > 0 and c > 0) and
(a == (b + c) or b == (a + c) or
c == (a + b))):
return True
return False
@timing
def p091():
combinations = []
for i in range(N + 1):
for j in range(N + 1):
combinations.append((i, j))
prods = product(combinations, repeat=2)
count = 0
for p in prods:
if check_triangle((0, 0), p[0], p[1]):
count += 1
print('Project Euler, Problem 91')
print(f'Answer: {int(count / 2)}')
if __name__ == '__main__':
p091()

View File

@ -4,3 +4,4 @@ These are my solutions in C and Python, not necessarily the best solutions. I've
# 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 88, 90 and 91 have been implemented in Python but not in C.