I was looking at the accepted solution to this question, which provides a Python implementation of an algorithm for producing unique permutations in lexicographic order. I have a somewhat shortened implementation:
def permutations(seq):
seq = sorted(seq)
while True:
yield seq
k = l = None
for k in range(len(seq) - 1):
if seq[k] < seq[k + 1]:
l = k + 1
break
else:
return
(seq[k], seq[l]) = (seq[l], seq[k])
seq[k + 1:] = seq[-1:k:-1]
What's really strange for me is that if I call list
on the output of this function, I get wrong results. However, if I iterate over the results of this function one at a time, I get the expected results.
>>> list(permutations((1,2,1)))
[[2, 1, 1], [2, 1, 1], [2, 1, 1]]
>>> for p in permutations((1,2,1)):
... print(p)
...
[1, 1, 2]
[1, 2, 1]
[2, 1, 1]
^^^What the?! Another example:
>>> list(permutations((1,2,3)))
[[3, 2, 1], [3, 2, 1], [3, 2, 1], [3, 2, 1]]
>>> for p in permutations((1,2,3)):
... print(p)
...
[1, 2, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
And list comprehension also yields the incorrect values:
>>> [p for p in permutations((1,2,3))]
[[3, 2, 1], [3, 2, 1], [3, 2, 1], [3, 2, 1]]
I have no idea what's going on here! I've not seen this before. I can write other functions that use generators and I don't run into this:
>>> def seq(n):
... for i in range(n):
... yield i
...
>>> list(seq(5))
[0, 1, 2, 3, 4]
What's going on in my example above that causes this?