Lets N
be a number (10<=N<=10^5)
.
I have to break it into 3 numbers (x,y,z)
such that it validates the following conditions.
Here is a simple improvement in Python (converting to the faster equivalent in C-based code is left as an exercise for the reader). To get accurate timing for the computation, I removed printing the solutions themselves (after validating them in a previous run).
z
), constrained only by its relation to N
. y
) constrained by the outer loop index. Timing results:
-------------------- 10
1 solutions found in 2.3365020751953125e-05 sec.
-------------------- 100
6 solutions found in 0.00040078163146972656 sec.
-------------------- 1000
55 solutions found in 0.030081748962402344 sec.
-------------------- 10000
543 solutions found in 2.2078349590301514 sec.
-------------------- 100000
5512 solutions found in 214.93411707878113 sec.
That's 3:35 for the large case, plus your time to collate and/or print the results.
If you need faster code (this is still pretty brute-force), look into Diophantine equations and parameterizations to generate (y, x)
pairs, given the target value of z^2 - 1
.
import math
import time
def break3(N):
"""
10 <= N <= 10^5
return x, y, z triples such that:
x <= y <= z
x^2 + y^2 = z^2 - 1
x + y + z <= N
"""
"""
Observations:
z <= x + y
z < N/2
"""
count = 0
z_limit = N // 2
for z in range(3, z_limit):
# Since y >= x, there's a lower bound on y
target = z*z - 1
ymin = int(math.sqrt(target/2))
for y in range(ymin, z):
# Given y and z, compute x.
# That's a solution iff x is integer.
x_target = target - y*y
x = int(math.sqrt(x_target))
if x*x == x_target and x+y+z <= N:
# print("solution", x, y, z)
count += 1
return count
test = [10, 100, 1000, 10**4, 10**5]
border = "-"*20
for case in test:
print(border, case)
start = time.time()
print(break3(case), "solutions found in", time.time() - start, "sec.")