Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python shuffle such that position will never repeat

I'd like to do a random shuffle of a list but with one condition: an element can never be in the same original position after the shuffle.

Is there a one line way to do such in python for a list?

Example:

list_ex = [1,2,3]

each of the following shuffled lists should have the same probability of being sampled after the shuffle:

list_ex_shuffled = [2,3,1]
list_ex_shuffled = [3,1,2]

but the permutations [1,2,3], [1,3,2], [2,1,3] and [3,2,1] are not allowed since all of them repeat one of the elements positions.

NOTE: Each element in the list_ex is a unique id. No repetition of the same element is allowed.

Any ideas? thanks!

like image 699
Dnaiel Avatar asked Mar 19 '13 22:03

Dnaiel


People also ask

What does shuffle () do in Python?

The shuffle() method takes a sequence, like a list, and reorganize the order of the items. Note: This method changes the original list, it does not return a new list.

What is difference between shuffle () and Choice () function of random module?

The choice method only generates one random number, and uses it to index into the sequence it was given. The shuffle method, on the other hand, loops over the length of the sequence and swaps elements around as it goes. So choice will take O(1) time, while shuffle takes O(N) time.

Why random shuffle is not working in Python?

You will get an error if you try to shuffle a string using the shuffle() method. Because a string is an immutable type, and You can't modify the immutable objects in Python. The random. shuffle() doesn't' work with String.

How will you randomizes the items of a list in place?

The shuffle() method randomizes the items of a list in place.


2 Answers

Randomize in a loop and keep rejecting the results until your condition is satisfied:

import random

def shuffle_list(some_list):
    randomized_list = some_list[:]
    while True:
        random.shuffle(randomized_list)
        for a, b in zip(some_list, randomized_list):
            if a == b:
                break
        else:
            return randomized_list
like image 166
tdelaney Avatar answered Nov 06 '22 22:11

tdelaney


I'd describe such shuffles as 'permutations with no fixed points'. They're also known as derangements.

The probability that a random permutation is a derangement is approximately 1/e (fun to prove). This is true however long the list. Thus an obvious algorithm to give a random derangement is to shuffle the cards normally, and keep shuffling until you have a derangement. The expected number of necessary shuffles is about 3, and it's rare you'll have to shuffle more than ten times.

(1-1/e)**11 < 1%

Suppose there are n people at a party, each of whom brought an umbrella. At the end of the party, each person takes an umbrella at random from the basket. What is the probability that no-one holds their own umbrella?

like image 35
Colonel Panic Avatar answered Nov 06 '22 23:11

Colonel Panic