Roberto
Roberto

Reputation: 2194

Python (naive) shuffle in place -- towards reproducing Fisher-Yates

I am trying to reproduce the Fisher-Yates algorithm for shuffling an array in place:

The problem is that when I run the first step for a "naive" shuffle, my results come up very even; I do not see the skew expected for some of the combinations. I have run up to 6 million trials:

I suspect there is something "wrong" with my implementation and would appreciate feedback.

Here is the code I am using:

import random
from pprint import pprint

runLength = 600000

cards = [1, 2, 3]
sequenceCount = {'123':0, '132':0, '213':0, '231':0, '312':0, '321':0}

for k in range(runLength):

    # naive shuffle
    for i,v in enumerate(cards):
        n = random.randint(0, len(cards)-1)
        cards[i], cards[n] = cards[n], cards[i] #swap

    # track results
    strDeck = ''
    for j,v in enumerate(cards):
        strDeck = strDeck + str(cards[j])
    sequenceCount[strDeck] = sequenceCount[strDeck] + 1

# results summary
pprint(sequenceCount)

Upvotes: 1

Views: 595

Answers (1)

Ahha, the problem is that you reshuffle the cards again and again, instead of always using the [ 1, 2, 3 ] as the starting point. Moreover your python is very unidiomatic and a bit hard to read, so let me rewrite it for you ;)

import random
from pprint import pprint
from collections import Counter

runLength = 600000

sequenceCount = Counter()
originalCards = ["1", "2", "3"]
ncards = len(originalCards)

for k in range(runLength): # use xrange on python 2
    cards = list(originalCards)

    # naive shuffle        
    for i in range(ncards):
        n = random.randint(0, ncards - 1)
        cards[i], cards[n] = cards[n], cards[i] #swap

    sequenceCount[''.join(cards)] += 1

# results summary
print(sequenceCount)

# result: Counter({'132': 111424, '231': 111194, '213': 110312, 
#                  '123': 89533, '321': 88846, '312': 88691})

Upvotes: 1

Related Questions