Source code for ecgenpy.sjt

""" Steinhaus-Johnson-Trotter algorithm """
from typing import Generator


[docs] def SJT_gen(n: int) -> Generator: """ The function `SJT_gen` generates all permutations of length `n` using the Steinhaus-Johnson-Trotter algorithm. Note: The list returns to the original permutations after all swaps. :param n: The parameter `n` represents the number of elements in the permutation :type n: int :return: The function `SJT_gen` returns a generator object. Examples: >>> for i in SJT_gen(4): ... print("swap {} and {}".format(i, i + 1)) ... swap 2 and 3 swap 1 and 2 swap 0 and 1 swap 2 and 3 swap 0 and 1 swap 1 and 2 swap 2 and 3 swap 0 and 1 swap 2 and 3 swap 1 and 2 swap 0 and 1 swap 2 and 3 swap 0 and 1 swap 1 and 2 swap 2 and 3 swap 0 and 1 swap 2 and 3 swap 1 and 2 swap 0 and 1 swap 2 and 3 swap 0 and 1 swap 1 and 2 swap 2 and 3 swap 0 and 1 """ if n == 2: yield 0 yield 0 # tricky part: return to the origin return up = range(n - 1) down = range(n - 2, -1, -1) gen = SJT_gen(n - 1) for x in gen: for i in down: # downward yield i yield x + 1 for i in up: # upward yield i yield next(gen) # tricky part
[docs] def SJT(n: int) -> Generator: """ The function `SJT` generates all permutations of length `n` using the Steinhaus-Johnson-Trotter algorithm. :param n: The parameter `n` represents the number of elements in the permutation :type n: int :return: The function `SJT` returns a generator object. Examples: >>> fruits = list("🍉🍌🍇🍏") >>> for lst in SJT(4): ... mylst = list(fruits[i] for i in lst) ... print("".join(mylst)) ... 🍉🍌🍇🍏 🍉🍌🍏🍇 🍉🍏🍌🍇 🍏🍉🍌🍇 🍏🍉🍇🍌 🍉🍏🍇🍌 🍉🍇🍏🍌 🍉🍇🍌🍏 🍇🍉🍌🍏 🍇🍉🍏🍌 🍇🍏🍉🍌 🍏🍇🍉🍌 🍏🍇🍌🍉 🍇🍏🍌🍉 🍇🍌🍏🍉 🍇🍌🍉🍏 🍌🍇🍉🍏 🍌🍇🍏🍉 🍌🍏🍇🍉 🍏🍌🍇🍉 🍏🍌🍉🍇 🍌🍏🍉🍇 🍌🍉🍏🍇 🍌🍉🍇🍏 """ perm = list(range(n)) for x in SJT_gen(n): yield perm perm[x], perm[x + 1] = perm[x + 1], perm[x]
[docs] def PlainChanges(n): """Generate the swaps for the Steinhaus-Johnson-Trotter algorithm (original method).""" if n < 1: return up = range(n - 1) down = range(n - 2, -1, -1) recur = PlainChanges(n - 1) try: while True: for x in down: yield x yield next(recur) + 1 for x in up: yield x yield next(recur) except StopIteration: pass
if __name__ == "__main__": # import doctest # doctest.testmod() # fruits = list("🍉🍌🍇🍏") fruits = list("ABCD") for lst in SJT(4): mylst = list(fruits[i] for i in lst) print("".join(mylst))