forked from TheAlgorithms/Python
- Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsol1.py
174 lines (142 loc) · 5.63 KB
/
sol1.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
"""
Project Euler Problem 234: https://projecteuler.net/problem=234
For any integer n, consider the three functions
f1,n(x,y,z) = x^(n+1) + y^(n+1) - z^(n+1)
f2,n(x,y,z) = (xy + yz + zx)*(x^(n-1) + y^(n-1) - z^(n-1))
f3,n(x,y,z) = xyz*(xn-2 + yn-2 - zn-2)
and their combination
fn(x,y,z) = f1,n(x,y,z) + f2,n(x,y,z) - f3,n(x,y,z)
We call (x,y,z) a golden triple of order k if x, y, and z are all rational numbers
of the form a / b with 0 < a < b ≤ k and there is (at least) one integer n,
so that fn(x,y,z) = 0.
Let s(x,y,z) = x + y + z.
Let t = u / v be the sum of all distinct s(x,y,z) for all golden triples
(x,y,z) of order 35.
All the s(x,y,z) and t must be in reduced form.
Find u + v.
Solution:
By expanding the brackets it is easy to show that
fn(x, y, z) = (x + y + z) * (x^n + y^n - z^n).
Since x,y,z are positive, the requirement fn(x, y, z) = 0 is fulfilled if and
only if x^n + y^n = z^n.
By Fermat's Last Theorem, this means that the absolute value of n can not
exceed 2, i.e. n is in {-2, -1, 0, 1, 2}. We can eliminate n = 0 since then the
equation would reduce to 1 + 1 = 1, for which there are no solutions.
So all we have to do is iterate through the possible numerators and denominators
of x and y, calculate the corresponding z, and check if the corresponding numerator and
denominator are integer and satisfy 0 < z_num < z_den <= 0. We use a set "uniquq_s"
to make sure there are no duplicates, and the fractions.Fraction class to make sure
we get the right numerator and denominator.
Reference:
https://en.wikipedia.org/wiki/Fermat%27s_Last_Theorem
"""
from __future__ importannotations
fromfractionsimportFraction
frommathimportgcd, sqrt
defis_sq(number: int) ->bool:
"""
Check if number is a perfect square.
>>> is_sq(1)
True
>>> is_sq(1000001)
False
>>> is_sq(1000000)
True
"""
sq: int=int(number**0.5)
returnnumber==sq*sq
defadd_three(
x_num: int, x_den: int, y_num: int, y_den: int, z_num: int, z_den: int
) ->tuple[int, int]:
"""
Given the numerators and denominators of three fractions, return the
numerator and denominator of their sum in lowest form.
>>> add_three(1, 3, 1, 3, 1, 3)
(1, 1)
>>> add_three(2, 5, 4, 11, 12, 3)
(262, 55)
"""
top: int=x_num*y_den*z_den+y_num*x_den*z_den+z_num*x_den*y_den
bottom: int=x_den*y_den*z_den
hcf: int=gcd(top, bottom)
top//=hcf
bottom//=hcf
returntop, bottom
defsolution(order: int=35) ->int:
"""
Find the sum of the numerator and denominator of the sum of all s(x,y,z) for
golden triples (x,y,z) of the given order.
>>> solution(5)
296
>>> solution(10)
12519
>>> solution(20)
19408891927
"""
unique_s: set=set()
hcf: int
total: Fraction=Fraction(0)
fraction_sum: tuple[int, int]
forx_numinrange(1, order+1):
forx_deninrange(x_num+1, order+1):
fory_numinrange(1, order+1):
fory_deninrange(y_num+1, order+1):
# n=1
z_num=x_num*y_den+x_den*y_num
z_den=x_den*y_den
hcf=gcd(z_num, z_den)
z_num//=hcf
z_den//=hcf
if0<z_num<z_den<=order:
fraction_sum=add_three(
x_num, x_den, y_num, y_den, z_num, z_den
)
unique_s.add(fraction_sum)
# n=2
z_num= (
x_num*x_num*y_den*y_den+x_den*x_den*y_num*y_num
)
z_den=x_den*x_den*y_den*y_den
ifis_sq(z_num) andis_sq(z_den):
z_num=int(sqrt(z_num))
z_den=int(sqrt(z_den))
hcf=gcd(z_num, z_den)
z_num//=hcf
z_den//=hcf
if0<z_num<z_den<=order:
fraction_sum=add_three(
x_num, x_den, y_num, y_den, z_num, z_den
)
unique_s.add(fraction_sum)
# n=-1
z_num=x_num*y_num
z_den=x_den*y_num+x_num*y_den
hcf=gcd(z_num, z_den)
z_num//=hcf
z_den//=hcf
if0<z_num<z_den<=order:
fraction_sum=add_three(
x_num, x_den, y_num, y_den, z_num, z_den
)
unique_s.add(fraction_sum)
# n=2
z_num=x_num*x_num*y_num*y_num
z_den= (
x_den*x_den*y_num*y_num+x_num*x_num*y_den*y_den
)
ifis_sq(z_num) andis_sq(z_den):
z_num=int(sqrt(z_num))
z_den=int(sqrt(z_den))
hcf=gcd(z_num, z_den)
z_num//=hcf
z_den//=hcf
if0<z_num<z_den<=order:
fraction_sum=add_three(
x_num, x_den, y_num, y_den, z_num, z_den
)
unique_s.add(fraction_sum)
fornum, deninunique_s:
total+=Fraction(num, den)
returntotal.denominator+total.numerator
if__name__=="__main__":
print(f"{solution() =}")