Generating unique, ordered Pythagorean triplets

前端 未结 19 1188
借酒劲吻你
借酒劲吻你 2020-11-29 16:57

This is a program I wrote to calculate Pythagorean triplets. When I run the program it prints each set of triplets twice because of the if statement. Is there any way I can

相关标签:
19条回答
  • 2020-11-29 17:28

    It should be noted that for a, b, and c you don't need to loop all the way to N.

    For a, you only have to loop from 1 to int(sqrt(n**2/2))+1, for b, a+1 to int(sqrt(n**2-a**2))+1, and for c from int(sqrt(a**2+b**2) to int(sqrt(a**2+b**2)+2.

    0 讨论(0)
  • 2020-11-29 17:28

    U have to use Euclid's proof of Pythagorean triplets. Follow below...

    U can choose any arbitrary number greater than zero say m,n

    According to Euclid the triplet will be a(m*m-n*n), b(2*m*n), c(m*m+n*n)

    Now apply this formula to find out the triplets, say our one value of triplet is 6 then, other two? Ok let’s solve...

    a(m*m-n*n), b(2*m*n) , c(m*m+n*n)

    It is sure that b(2*m*n) is obviously even. So now

    (2*m*n)=6 =>(m*n)=3 =>m*n=3*1 =>m=3,n=1

    U can take any other value rather than 3 and 1, but those two values should hold the product of two numbers which is 3 (m*n=3)

    Now, when m=3 and n=1 Then,

    a(m*m-n*n)=(3*3-1*1)=8 , c(m*m-n*n)=(3*3+1*1)=10

    6,8,10 is our triplet for value, this our visualization of how generating triplets.

    if given number is odd like (9) then slightly modified here, because b(2*m*n)

    will never be odd. so, here we have to take

    a(m*m-n*n)=7, (m+n)*(m-n)=7*1, So, (m+n)=7, (m-n)=1

    Now find m and n from here, then find the other two values.

    If u don’t understand it, read it again carefully.

    Do code according this, it will generate distinct triplets efficiently.

    0 讨论(0)
  • 2020-11-29 17:30

    Old Question, but i'll still input my stuff. There are two general ways to generate unique pythagorean triples. One Is by Scaling, and the other is by using this archaic formula.

    What scaling basically does it take a constant n, then multiply a base triple, lets say 3,4,5 by n. So taking n to be 2, we get 6,8,10 our next triple.

    Scaling

    def pythagoreanScaled(n):
        triplelist = []
        for x in range(n):
            one = 3*x
            two = 4*x
            three = 5*x
            triple = (one,two,three)
            triplelist.append(triple)
    return triplelist
    

    The formula method uses the fact the if we take a number x, calculate 2m, m^2+1, and m^2-1, those three will always be a pythagorean triplet.

    Formula

    def pythagoreantriple(n):
        triplelist = []
        for x in range(2,n):
            double = x*2
            minus = x**2-1
            plus = x**2+1
            triple = (double,minus,plus)
            triplelist.append(triple)
        return triplelist
    
    0 讨论(0)
  • 2020-11-29 17:30
    # To find all pythagorean triplets in a range
    import math
    n = int(input('Enter the upper range of limit'))
    for i in range(n+1):
        for j in range(1, i):
            k = math.sqrt(i*i + j*j)
            if k % 1 == 0 and k in range(n+1):
                print(i,j,int(k))
    
    0 讨论(0)
  • 2020-11-29 17:36
    from  math import sqrt
    from itertools import combinations
    
    #Pythagorean triplet - a^2 + b^2 = c^2 for (a,b) <= (1999,1999)
    def gen_pyth(n):
    if n >= 2000 :
      return
    ELEM =   [  [ i,j,i*i + j*j ] for i , j in list(combinations(range(1, n +   1 ), 2)) if sqrt(i*i + j*j).is_integer() ]
    print (*ELEM , sep = "\n")
    
    
    gen_pyth(200)
    
    0 讨论(0)
  • 2020-11-29 17:39

    Pythagorean Triples make a good example for claiming "for loops considered harmful", because for loops seduce us into thinking about counting, often the most irrelevant part of a task.

    (I'm going to stick with pseudo-code to avoid language biases, and to keep the pseudo-code streamlined, I'll not optimize away multiple calculations of e.g. x * x and y * y.)

    Version 1:

    for x in 1..N {
        for y in 1..N {
            for z in 1..N {
                if x * x + y * y == z * z then {
                    // use x, y, z
                }
            }
        }
    }
    

    is the worst solution. It generates duplicates, and traverses parts of the space that aren't useful (e.g. whenever z < y). Its time complexity is cubic on N.

    Version 2, the first improvement, comes from requiring x < y < z to hold, as in:

    for x in 1..N {
        for y in x+1..N {
            for z in y+1..N {
                if x * x + y * y == z * z then {
                    // use x, y, z
                }
            }
        }
    }
    

    which reduces run time and eliminates duplicated solutions. However, it is still cubic on N; the improvement is just a reduction of the co-efficient of N-cubed.

    It is pointless to continue examining increasing values of z after z * z < x * x + y * y no longer holds. That fact motivates Version 3, the first step away from brute-force iteration over z:

    for x in 1..N {
        for y in x+1..N {
            z = y + 1
            while z * z < x * x + y * y {
                z = z + 1
            }
            if z * z == x * x + y * y and z <= N then {
                // use x, y, z
            }
        }
    }
    

    For N of 1000, this is about 5 times faster than Version 2, but it is still cubic on N.

    The next insight is that x and y are the only independent variables; z depends on their values, and the last z value considered for the previous value of y is a good starting search value for the next value of y. That leads to Version 4:

    for x in 1..N {
        y = x+1
        z = y+1
        while z <= N {
            while z * z < x * x + y * y {
                z = z + 1
            }
            if z * z == x * x + y * y and z <= N then {
                // use x, y, z
            }
            y = y + 1
        }
    }
    

    which allows y and z to "sweep" the values above x only once. Not only is it over 100 times faster for N of 1000, it is quadratic on N, so the speedup increases as N grows.

    I've encountered this kind of improvement often enough to be mistrustful of "counting loops" for any but the most trivial uses (e.g. traversing an array).

    Update: Apparently I should have pointed out a few things about V4 that are easy to overlook.

    1. Both of the while loops are controlled by the value of z (one directly, the other indirectly through the square of z). The inner while is actually speeding up the outer while, rather than being orthogonal to it. It's important to look at what the loops are doing, not merely to count how many loops there are.

    2. All of the calculations in V4 are strictly integer arithmetic. Conversion to/from floating-point, as well as floating-point calculations, are costly by comparison.

    3. V4 runs in constant memory, requiring only three integer variables. There are no arrays or hash tables to allocate and initialize (and, potentially, to cause an out-of-memory error).

    4. The original question allowed all of x, y, and x to vary over the same range. V1..V4 followed that pattern.

    Below is a not-very-scientific set of timings (using Java under Eclipse on my older laptop with other stuff running...), where the "use x, y, z" was implemented by instantiating a Triple object with the three values and putting it in an ArrayList. (For these runs, N was set to 10,000, which produced 12,471 triples in each case.)

    Version 4:           46 sec.
    using square root:  134 sec.
    array and map:      400 sec.
    

    The "array and map" algorithm is essentially:

    squares = array of i*i for i in 1 .. N
    roots = map of i*i -> i for i in 1 .. N
    for x in 1 .. N
        for y in x+1 .. N
            z = roots[squares[x] + squares[y]]
            if z exists use x, y, z
    

    The "using square root" algorithm is essentially:

    for x in 1 .. N
        for y in x+1 .. N
            z = (int) sqrt(x * x + y * y)
            if z * z == x * x + y * y then use x, y, z
    

    The actual code for V4 is:

    public Collection<Triple> byBetterWhileLoop() {
        Collection<Triple> result = new ArrayList<Triple>(limit);
        for (int x = 1; x < limit; ++x) {
            int xx = x * x;
            int y = x + 1;
            int z = y + 1;
            while (z <= limit) {
                int zz = xx + y * y;
                while (z * z < zz) {++z;}
                if (z * z == zz && z <= limit) {
                    result.add(new Triple(x, y, z));
                }
                ++y;
            }
        }
        return result;
    }
    

    Note that x * x is calculated in the outer loop (although I didn't bother to cache z * z); similar optimizations are done in the other variations.

    I'll be glad to provide the Java source code on request for the other variations I timed, in case I've mis-implemented anything.

    0 讨论(0)
提交回复
热议问题