1

I'm trying to generate all permutations of a list subject to the constraint that there are no duplicates by rotation. So if I were doing this for lists of length 3, doing normal permutations I would get both [1, 2, 3] and [2, 3, 1]. However, [2, 3, 1] is just a rotation of [1, 2, 3] and so I don't want to include it.

I could generate all permutations, loop through and remove elements that violate this constraint but this seems wasteful.

How could I do this as I consider permutations, instead of considering all permutations and then removing duplicated ones?

Thanks!

anon_swe
  • 8,791
  • 24
  • 85
  • 145

1 Answers1

3

Take the first element off, generate permutations of the other elements, and stick the first element back onto the front of every permutation. This will generate one representative of every rotational equivalence class, specifically the representative where the original first element is still first.

import itertools

def permutations(iterable):
    # Special case: empty iterable
    iterable = list(iterable)
    if not iterable:
        yield ()
        return

    first, *rest = iterable
    for subperm in itertools.permutations(rest):
        yield (first, *subperm)
user2357112
  • 260,549
  • 28
  • 431
  • 505