Ejemplo n.º 1
0
def triples():
    """ generates all Pythagorean triplets triplets x<y<z 
    sorted by hypotenuse z, then longest side y
    """
    prim=[] #list of primitive triples up to now
    key=lambda x:(x[2],x[1])
    samez=SortedCollection(key=key) # temp triplets with same z
    buffer=SortedCollection(key=key) # temp for triplets with smaller z
    for pt in primitive_triples():
        z=pt[2]
        if samez and z!=samez[0][2]: #flush samez
            while samez:
                yield samez.pop(0)
        samez.insert(pt)
        #build buffer of smaller multiples of the primitives already found
        for i,pm in enumerate(prim):
            p,m=pm[0:2]
            while True:
                mz=m*p[2]
                if mz < z:
                    buffer.insert(tuple(m*x for x in p))
                elif mz == z: 
                    # we need another buffer because next pt might have
                    # the same z as the previous one, but a smaller y than
                    # a multiple of a previous pt ...
                    samez.insert(tuple(m*x for x in p))
                else:
                    break
                m+=1
            prim[i][1]=m #update multiplier for next loops
        while buffer: #flush buffer
            yield buffer.pop(0)
        prim.append([pt,2]) #add primitive to the list
Ejemplo n.º 2
0
def sorted_iterable(iterable, key=None, buffer=100):
    """sorts an almost sorted (infinite) iterable
    :param iterable: iterable
    :param key: function used as sort key
    :param buffer: int size of buffer. elements to swap should not be further than that
    """
    from Goulib.container import SortedCollection
    b=SortedCollection(key=key)
    for x in iterable:
        if len(b)>=buffer:
            yield b.pop(0)
        b.insert(x)
    for x in b: yield x # this never happens if iterable is infinite
Ejemplo n.º 3
0
def sorted_iterable(iterable, key=None, buffer=100):
    """sorts an "almost sorted" (infinite) iterable
    :param iterable: iterable
    :param key: function used as sort key
    :param buffer: int size of buffer. elements to swap should not be further than that
    """
    key = key or identity
    from Goulib.container import SortedCollection
    b = SortedCollection(key=key)
    for x in iterable:
        if len(b) >= buffer:
            res = b.pop(0)
            yield res
        b.insert(x)
    for x in b:  # this never happens if iterable is infinite
        yield x
Ejemplo n.º 4
0
def primitive_triples():
    """ generates primitive Pythagorean triplets x<y<z
    sorted by hypotenuse z, then longest side y
    through Berggren's matrices and breadth first traversal of ternary tree
    :see: https://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
    """
    key = lambda x: (x[2], x[1])
    triples = SortedCollection(key=key)
    triples.insert([3, 4, 5])
    A = [[1, -2, 2], [2, -1, 2], [2, -2, 3]]
    B = [[1, 2, 2], [2, 1, 2], [2, 2, 3]]
    C = [[-1, 2, 2], [-2, 1, 2], [-2, 2, 3]]

    while triples:
        (a, b, c) = triples.pop(0)
        yield (a, b, c)

        # expand this triple to 3 new triples using Berggren's matrices
        for X in [A, B, C]:
            triple = [
                sum(x * y for (x, y) in zip([a, b, c], X[i])) for i in range(3)
            ]
            if triple[0] > triple[1]:  # ensure x<y<z
                triple[0], triple[1] = triple[1], triple[0]
            triples.insert(triple)
Ejemplo n.º 5
0
def primitive_triples():
    """ generates primitive Pythagorean triplets x<y<z
    sorted by hypotenuse z, then longest side y
    through Berggren's matrices and breadth first traversal of ternary tree
    :see: https://en.wikipedia.org/wiki/Tree_of_primitive_Pythagorean_triples
    """
    key=lambda x:(x[2],x[1])
    triples=SortedCollection(key=key)
    triples.insert([3,4,5])
    A = [[ 1,-2, 2], [ 2,-1, 2], [ 2,-2, 3]]
    B = [[ 1, 2, 2], [ 2, 1, 2], [ 2, 2, 3]]
    C = [[-1, 2, 2], [-2, 1, 2], [-2, 2, 3]]

    while triples:
        (a,b,c) = triples.pop(0)
        yield (a,b,c)

        # expand this triple to 3 new triples using Berggren's matrices
        for X in [A,B,C]:
            triple=[sum(x*y for (x,y) in zip([a,b,c],X[i])) for i in range(3)]
            if triple[0]>triple[1]: # ensure x<y<z
                triple[0],triple[1]=triple[1],triple[0]
            triples.insert(triple)
Ejemplo n.º 6
0
def triples():
    """ generates all Pythagorean triplets triplets x<y<z
    sorted by hypotenuse z, then longest side y
    """
    prim = []  #list of primitive triples up to now
    key = lambda x: (x[2], x[1])
    samez = SortedCollection(key=key)  # temp triplets with same z
    buffer = SortedCollection(key=key)  # temp for triplets with smaller z
    for pt in primitive_triples():
        z = pt[2]
        if samez and z != samez[0][2]:  #flush samez
            while samez:
                yield samez.pop(0)
        samez.insert(pt)
        #build buffer of smaller multiples of the primitives already found
        for i, pm in enumerate(prim):
            p, m = pm[0:2]
            while True:
                mz = m * p[2]
                if mz < z:
                    buffer.insert(tuple(m * x for x in p))
                elif mz == z:
                    # we need another buffer because next pt might have
                    # the same z as the previous one, but a smaller y than
                    # a multiple of a previous pt ...
                    samez.insert(tuple(m * x for x in p))
                else:
                    break
                m += 1
            prim[i][1] = m  #update multiplier for next loops
        while buffer:  #flush buffer
            yield buffer.pop(0)
        prim.append([pt, 2])  #add primitive to the list