I want to generate all possible permutations of a list, where cyclic permutations (going from left to right) should only occur once.
Here is an example:
Let the list be [A, B, C]. Then I want to have permutations such as [A, C, B] but not [B, C, A] as this would be a circular permutation of the original list [A, B, C]. For the list above, the result should look like
[A, B, C]
[A, C, B]
[B, A, C]
[C, B, A]
Here is a minimal working example that uses permutations() from itertools.
from itertools import permutations
def permutations_without_cycles(seq: list):
# Get a list of all permutations
permutations_all = list(permutations(seq))
print("\nAll permutations:")
for i, p in enumerate(permutations_all):
print(i, "\t", p)
# Get a list of all cyclic permutations
cyclic_permutations = [tuple(seq[i:] + seq[:i]) for i in range(len(seq))]
print("\nAll cyclic permutations:")
for i, p in enumerate(cyclic_permutations):
print(i, "\t", p)
# Remove all cyclic permutations except for one
cyclic_permutations = cyclic_permutations[1:] # keep one cycle
permutations_cleaned = [p for p in permutations_all if p not in cyclic_permutations]
print("\nCleaned permutations:")
for i, item in enumerate(permutations_cleaned):
print(i, "\t", item)
def main():
seq = ["A", "B", "C"]
permutations_without_cycles(seq=seq)
if __name__ == "__main__":
main()
I would like to know if there is a method in itertools to solve this problem for efficiently?
That's unusual, so no, that's not already in itertools. But we can optimize your way significantly (mainly by filtering out the unwanted cyclics by using a set instead of a list, or even by just the single next unwanted one). Even more efficiently, we can compute the indexes of the unwanted permutations[*] and
islicebetween them. See the full code at the bottom.[*] Using a simplified version of permutation_index from more-itertools.
Benchmark results, using
list(range(n))as the sequence. Ints compare fairly quickly, so if the sequence elements were some objects with more expensive comparisons, myefficientsolution would have an even bigger advantage, since it's the only one that doesn't rely on comparing permutations/elements.Code (Attempt This Online!):