def permutations(x):
    '''Given a listlike, x, return all permutations of x

    Returns the permutations of x in the lexical order of their indices:
    e.g.
    >>> x = [ 1, 2, 3, 4 ]
    >>> for p in permutations(x):
    >>>   print p
    [ 1, 2, 3, 4 ]
    [ 1, 2, 4, 3 ]
    [ 1, 3, 2, 4 ]
    [ 1, 3, 4, 2 ]
    [ 1, 4, 2, 3 ]
    [ 1, 4, 3, 2 ]
    [ 2, 1, 3, 4 ]
    ...
    [ 4, 3, 2, 1 ]
    '''
    #
    # The algorithm is attributed to Narayana Pandit from his
    # Ganita Kaumundi (1356). The following is from
    #
    # http://en.wikipedia.org/wiki/Permutation#Systematic_generation_of_all_permutations
    #
    # 1. Find the largest index k such that a[k] < a[k + 1].
    #    If no such index exists, the permutation is the last permutation.
    # 2. Find the largest index l such that a[k] < a[l].
    #    Since k + 1 is such an index, l is well defined and satisfies k < l.
    # 3. Swap a[k] with a[l].
    # 4. Reverse the sequence from a[k + 1] up to and including the final
    #    element a[n].
    #
    yield list(x) # don't forget to do the first one
    x = np.array(x)
    a = np.arange(len(x))
    while True:
        # 1 - find largest or stop
        ak_lt_ak_next = np.argwhere(a[:-1] < a[1:])
        if len(ak_lt_ak_next) == 0:
            raise StopIteration()
        k = ak_lt_ak_next[-1, 0]
        # 2 - find largest a[l] < a[k]
        ak_lt_al = np.argwhere(a[k] < a)
        l =  ak_lt_al[-1, 0]
        # 3 - swap
        a[k], a[l]  = (a[l], a[k])
        # 4 - reverse
        if k < len(x)-1:
            a[k+1:] = a[:k:-1].copy()
        yield x[a].tolist()