0

I'm trying to generate permutations of a list in order, but without enumerating all of the possible permutations. My algorithm is recursive, with a immutable "head" being passed to each sub-call, and the "tail" being permuted in order by the sub-call.

My understanding of "yield from" was that once the interior generator runs out of elements it's generating, the exterior generator continues on its code path. I'm getting confused though because the generator only generates the first permutation, and then raises a StopIteration exception on the next call to next.

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

def permutations(head, tail):
    if tail == []:
        yield head
    else:
        for num in tail:
            new_head = head + [num]
            new_tail = tail
            new_tail.remove(num)
            yield from permutations(new_head, new_tail)

perm_generator = permutations([], nums)

for i in range(1000000):
    res = next(perm_generator)
    print(res)

Output is:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
Traceback (most recent call last):
  File "024.py", line 19, in <module>
    res = next(perm_generator)
StopIteration

I know itertools makes this easy, but I'd like to do this with custom generators.

The most similar previous questions I've found are here and I guess here. What am I misunderstanding/doing wrong?

Jeremy
  • 104
  • 3
  • 12
  • 1
    You need to change `new_tail = tail` to `new_tail = tail.copy()`, otherwise the recursive `permutations` call modifies your `tail` list. – Aran-Fey Sep 20 '18 at 19:36
  • why are you calling `next` manually? Just use `for res in perm_generator: print(res)` – juanpa.arrivillaga Sep 20 '18 at 19:41
  • Yep, it was just the list mutation issue, thanks! @juanpa.arrivillaga , I didn't do that because I want to be able to break early and easily. I could keep a counter an manually `break`, but I though this would be better? Unfortunately you can't slice generator either. – Jeremy Sep 20 '18 at 19:43
  • @Jeremy you can, you have to use `itertools.islice`. – juanpa.arrivillaga Sep 20 '18 at 20:29

0 Answers0