Farid Darabi
Farid Darabi

Reputation: 99

can anyone optimize my python code for "Pythagorean triplets"?

I have written a code to find Pythagorean triplets but it is not optimized

it took 5-6 minutes for the algorithm to find answer for big numbers... my teacher said it should take less than 3 secs...


num = int(input())

def main(n):
    for x in range(1, n):
        for y in range(1, x):
            for z in range(1, y):
                if x + y + z == n:
                    if x * x == y * y + z * z or y * y == x * x + z * z or z * z == x * x + y * y:
                        a = f'{z} {y} {x}'
                        print(a)
                        return

    else:
        print('Impossible')

for example if you enter 12, you'll get 3,4,5 if you enter 30 , the answer will be 5,12,13

The sum of these three numbers must be equal to the number you entered.

can anyone please help me ?

Upvotes: 0

Views: 294

Answers (3)

felipe
felipe

Reputation: 8025

Note the proof for the parametric representation of primitive pythagorean triples. In the proof, the author states:

enter image description here

We can use this proof to write an optimized algorithm:

def p(num):
    a, b, c = 1, 1, 0
    n = 0

    while c < num:
        for m in range(1, n):
            a = 2 * m * n
            b = n ** 2 - m ** 2
            c = n ** 2 + m ** 2

            if c >= num:
                return "Impossible!"
            elif a + b + c == num:
                return b, a, c

        n = n + 1
print(p(12)) # >>> (3, 4, 5)
print(p(30)) # >>> (5, 12, 13)
print(p(31)) # >>> Impossible!

Upvotes: 1

Deepak Tatyaji Ahire
Deepak Tatyaji Ahire

Reputation: 5309

The approach you discussed takes O(n^3) complexity.

An efficient solution is to run two loops, where first loop runs from x = 1 to n/3, second loop runs from y = x+1 to n/2. In second loop, we check if (n – x – y) is equal to (x * x + y * y):

def pythagoreanTriplet(n): 

    # Considering triplets in  
    # sorted order. The value  
    # of first element in sorted  
    # triplet can be at-most n/3. 
    for x in range(1, int(n / 3) + 1):  

        # The value of second element  
        # must be less than equal to n/2 
        for y in range(x + 1,  
                       int(n / 2) + 1):  

            z = n - x - y 
            if (x * x + y * y == z * z):  
                print(x, " ", y, " ",  z)
                return

    print("Impossible") 

# Driver Code 
n = int(input())
pythagoreanTriplet(n)

PS: Time complexity = O(n^2)

Upvotes: 0

Chrispresso
Chrispresso

Reputation: 4071

You're doing a lot of repeated and unnecessary work. You know that A^2 + B^2 = C^2 and you know that C > B > A. It doesn't matter if you want to say C > A > B because any solution you find with that would be satisfied with C > B > A. For instance take 12 and solution 3, 4, 5. It doesn't actually matter if you say that A=3 and B=4 or A=4 and B=3. Knowing this we can adjust the loops of each for loop.

A can go from 1 to num, that's fine. Technically it can go to a bit less since you are adding another value to it that has to be at least 1 as well.

B then can go from A+1 to num since it needs to be greater than it.

So what about C? Well it doesnt' need to go from 1 since that's not possible. In fact we only care about A + B + C = num, so solve for C and you get C = num - A - B. That means you don't need to use a loop to find C since you can just solve for it. Knowing this you can do something like so:

In [142]: def find_triplet(num): 
 ...:     for a in range(1, num-1): 
 ...:         for b in range(a+1, num): 
 ...:             # A^2 + B^2 = C^2 
 ...:             # And A+B+C = N 
 ...:             c = num - a - b 
 ...:             if c > 0:
 ...:                 if a*a + b*b == c*c: 
 ...:                     print(f'{a} {b} {c}') 
 ...:             else: 
 ...:                 break 
 ...:                                                                                                                    

In [143]: find_triplet(30)                                                                                                   
5 12 13

So why check to see if C > 0 and break otherwise? Well, if you know C = num - A - B and you are incrementing B, then once B becomes too large, C is going to continue to get more and more negative. Because of that you can check if C > 0 and if it's not, break out of that inner loop to have A increment and B reset.

Upvotes: 0

Related Questions