Apply a permutation sigma({j}) to an arbitrary sequence.

    :param sequence: Any finite length sequence ``[l_1,l_2,...l_n]``. If it is a list, tuple or str, the return type will be the same.
    :param permutation: permutation image tuple
    :type permutation: tuple
    :return: The permuted sequence ``[l_sigma(1), l_sigma(2), ..., l_sigma(n)]``
    :raise: BadPermutationError or ValueError

def permute(sequence, permutation):
    """Apply a permutation sigma({j}) to an arbitrary sequence.

    :param sequence: Any finite length sequence ``[l_1,l_2,...l_n]``. If it is a list, tuple or str, the return type will be the same.
    :param permutation: permutation image tuple
    :type permutation: tuple
    :return: The permuted sequence ``[l_sigma(1), l_sigma(2), ..., l_sigma(n)]``
    :raise: BadPermutationError or ValueError
    """
    if len(sequence) != len(permutation):
        raise ValueError((sequence, permutation))
    if not check_permutation(permutation):
        raise BadPermutationError(str(permutation))

    if type(sequence) in (list, tuple, str):
        constructor = type(sequence)
    else:
        constructor = list
    return constructor((sequence[p] for p in permutation))