Possible error in python code: Sequence of permutations does not change

A code has been created for limiting the number of permutations of a set having 66 zeroes, 33 ones and 33 twos to ‘‘1000’’
and that code is
‘’‘from itertools import permutations
letters=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
for count, perms in enumerate(permutations(letters)):
if count >= 1000: break
print(perms)’’’’
However, permutations show the same sequence time and again like this
(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)

(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)

(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
I want to ascertain the mistake in my code.

The issue is that the permutations() function assumes that all elements are unique. But since you have repeated elements, that’s not true. list(permutations([1, 1])) would return two elements: (1, 1), and the reverse (1, 1).

You might want to look at the package more_itertools and the distinct_permutations() function.

>>> from itertools import permutations
>>> from more_itertools import distinct_permutations
>>> list(permutations([1, 2, 2]))
[(1, 2, 2), (1, 2, 2), (2, 1, 2), (2, 2, 1), (2, 1, 2), (2, 2, 1)]
>>> list(distinct_permutations([1, 2, 2]))
[(1, 2, 2), (2, 1, 2), (2, 2, 1)]

The permutations function returns the permutations in a specific order,
not in random order. If the values being permuted are equal, you will
not see any change, even though they are being moved around, because
they all look the same.

Like this: suppose you permute the digits: 1, 2, 0. Then the result you
get will be:

1, 2, 0
1, 0, 2
2, 1, 0
2, 0, 1
0, 1, 2
0, 2, 1

and it is obvious that they are being permuted. But now suppose you
permute the digits 1, 2, 2. Then you get:

1, 2, 2  # (A)
1, 2, 2  # Looks the same as (A)
2, 1, 2  # (B)
2, 2, 1  # (C)
2, 1, 2  # Looks the same as (B)
2, 2, 1  # Looks the same as (C)

Now suppose you do the permutations of 2, 2, 2. They will all look the
same! But they are still be permuted.

2, 2, 2
2, 2, 2  # Swap the last two digits.
2, 2, 2  # Swap the first two digits.
# and so on...

In your case, your sequence ends with not three identical 2s, but 33
identical 2s. Before you see anything change, the permutations function
has to move around the 33 identical 2s. There are factorial(33) =

8683317618811886495518194401280000000

permutations where just the digit 2s are being moved around, and you
will not see any change because they all look the same.

What can we do to change this? The simplest is to shuffle the initial
sequence into random order, jumble up the sequence so that you don’t
have huge runs of identical-looking permutations.

sequence = [1, 0, 0, 2]*33  # digits are grouped together
random.shuffle(sequence)

Now the digits will be jumbled up, and when permutations() moves them
around, it will be obvious.

I have tried this code
from more_itertools import distinct_permutations
letters=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]
for count, perms in enumerate(distinct_permutations(letters)):
if count >= 1000: break
print(perms)

but the problem is that it is giving only one result
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2)
what would you suggest is going wrong?

Ali123 said:

“the problem is that it is giving only one result”

I’m pretty sure it isn’t. I just tried it, and it works for me. Look
really carefully, and you will see that at the very end of the list
one digit changes position each time.

If you aren’t seeing any change, then start with a smaller set of
digits:

[1, 0, 0, 2]*2  # this will give you just 8 digits, not 132

and then look at how the permutations change. Then gradually increase
the 2 to 3, then 4, then 5, … to 33.

Both Python’s permutations function, and the more_itertools
distinct_permutations function, will produce the permutations by moving
one digit at a time. For a large set of digits, with many, many
duplicates, that can be hard to notice.

Maybe you should try using random.shuffle instead, which will give you a
random permutation each time.

Wait, I misread your code.

The reason your code is only printing one result is because you wait
until the loop has finished before you print the list, once.

So you generate a thousand different permutations, but forget to print
them. Then after breaking out of the loop, you finally print once.

# This only prints once.
for count, perms in enumerate(distinct_permutations(letters)):
    if count >= 1000: break
print(perms)  # <---- this is OUTSIDE the loop and only prints once.


# This prints 1000 times.
for count, perms in enumerate(distinct_permutations(letters)):
    if count >= 1000: break
    print(perms)  # <---- this is INSIDE the loop and prints each time.

It will help you see what you are doing if you use four spaces for each
indent, not one. With one space, it is too easy to make mistakes.

What text editor are you using to write your code? Any good programmer’s
text editor will let you press the TAB key to insert four spaces, and
either delete or SHIFT-TAB to remove four spaces from the start of the
line.

Thank you, your help made it easy for me to create my code.
Now, I want to create a code in which elements in every permutation more frequently change their positions.
Will for this random shuffle be a right approach?

Possibly. Your’s is so long that duplicates seem unlikely. But you could keep track of anything seen before and try again if it collides.

It’s probably best if the number of samples you need is (relatively) small.

import random

letters=[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2]

previously_seen = set()
random.shuffle(letters)

for pick in range(5):
    while tuple(letters) in previously_seen:
        random.shuffle(letters)
    print(letters)
    previously_seen.add(tuple(letters))

Thanks a lot for your help