# Generate successive k-length permutations. (4.00) # @note Rewrite of the code that appears at # docs.python.org/3/library/itertools.html#itertools.permutations # (restores indirect indexing) # @see 3UOMj3, vSELdo, cTaz9y def permutations(iterable, k=None): pool = tuple(iterable) n = len(pool) if k is None: k = n elif k > n: return index = list(range(n)) cycle = list(range(k)) while True: yield tuple(pool[i] for i in index[:k]) for i in reversed(range(k)): j = cycle[i] + 1 if j < n: cycle[i] = j index[i], index[j] = index[j], index[i] break cycle[i] = i index.append(index.pop(i)) else: return # Test. import itertools import time n = 3 a = list(range(n)) for k in range(2+len(a)): print(list(permutations(a, k))) print(list(itertools.permutations(a, k))) def test(f, a): t = time.process_time() for _ in f(a): pass t = time.process_time() - t print('Elapsed: {:.6f}s'.format(t)) m = sum(1 for _ in f(a)) n = sum(1 for _ in itertools.permutations(a)) assert m == n for x, y in zip(f(a), itertools.permutations(a)): assert x == y n = 8 a = list(range(n)) test(permutations, a) test(itertools.permutations, a)
Standard input is empty
[()] [()] [(0,), (1,), (2,)] [(0,), (1,), (2,)] [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)] [(0, 1), (0, 2), (1, 0), (1, 2), (2, 0), (2, 1)] [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)] [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0)] [] [] Elapsed: 0.065700s Elapsed: 0.004203s