Generating unique, ordered Pythagorean triplets

前端 未结 19 1300
借酒劲吻你
借酒劲吻你 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:51

    Substantially faster than any of the solutions so far. Finds triplets via a ternary tree.

    Wolfram says:

    Hall (1970) and Roberts (1977) prove that is a primitive Pythagorean triple if and only if

    (a,b,c)=(3,4,5)M

    where M is a finite product of the matrices U,A,D.

    And there we have a formula to generate every primitive triple.

    In the above formula, the hypotenuse is ever growing so it's pretty easy to check for a max length.

    In Python:

    import numpy as np
    
    def gen_prim_pyth_trips(limit=None):
        u = np.mat(' 1  2  2; -2 -1 -2; 2 2 3')
        a = np.mat(' 1  2  2;  2  1  2; 2 2 3')
        d = np.mat('-1 -2 -2;  2  1  2; 2 2 3')
        uad = np.array([u, a, d])
        m = np.array([3, 4, 5])
        while m.size:
            m = m.reshape(-1, 3)
            if limit:
                m = m[m[:, 2] <= limit]
            yield from m
            m = np.dot(m, uad)
    

    If you'd like all triples and not just the primitives:

    def gen_all_pyth_trips(limit):
        for prim in gen_prim_pyth_trips(limit):
            i = prim
            for _ in range(limit//prim[2]):
                yield i
                i = i + prim
    

    list(gen_prim_pyth_trips(10**4)) took 2.81 milliseconds to come back with 1593 elements while list(gen_all_pyth_trips(10**4)) took 19.8 milliseconds to come back with 12471 elements

    For reference, the accepted answer (in python) took 38 seconds for 12471 elements.

    Just for fun, setting the upper limit to one million list(gen_all_pyth_trips(10**6)) returns in 2.66 seconds with 1980642 elements (almost 2 million triples in 3 seconds). list(gen_all_pyth_trips(10**7)) brings my computer to its knees as the list gets so large it consumes every last bit of ram. Doing something like sum(1 for _ in gen_all_pyth_trips(10**7)) gets around that limitation and returns in 30 seconds with 23471475 elements.

    For more information on the algorithm used, check out the articles on Wolfram and Wikipedia.

提交回复
热议问题