# Distribution of matches between two shuffled decks

Take two desks of cards and shuffle them. They can be standard 52-card decks, though the number of cards in the decks doesn’t matter as long as they’re the same and the decks are fairly large.

Now count the number of times the two desks match, i.e. how many times the same card is in the same position in both desks. The number of matches is random, and its distribution is approximately Poisson with mean 1. Let’s do a simulation and see how close the results come to the predicted outcome.

Here’s the Python code:

```import numpy as np
from scipy.stats import poisson
import matplotlib.pyplot as plt

def count_zeros(x):
return len(x[x==0])

num_reps = 10000
deck_size = 52

matches = np.zeros(deck_size+1, dtype=int)

# Simulation
for _ in range(num_reps):

# Shuffle two decks
a = np.random.permutation(deck_size)
b = np.random.permutation(deck_size)

# Count how often they match
num_matches = count_zeros(a-b)
matches[ num_matches ] += 1

# Cut off outputs too small to see
cutoff = 8

# Matches predicted by a Poisson distribution with mean 1.
predicted = [num_reps*poisson(1).pmf(i) for i in range(cutoff)]

# Plot results
x = np.arange(cutoff)
w = 0.3 # bar width
plt.bar(x, matches[0:cutoff], w)
plt.bar(x+w, predicted, w)
plt.legend(["actual", "predicted"])
plt.xlabel("matches")
plt.ylabel("frequency")
plt.savefig("shuffled_desk_matches.svg")
plt.show()
```

And here’s the output based on 10,000 simulations: About 1/3 of the time, you get no matches, another 1/3 of the time you get one match, and the rest of the time you get more. More precisely, according to the Poisson model zero matches and one match are both have probability 1/e.

## 8 thoughts on “Distribution of matches between two shuffled decks”

1. Sam Hardwick

I think there’s a mistake in the count_zeros() function. First I thought, what a nifty syntax for filtering a list! How come I never saw that anywhere! But it doesn’t seem to work, x==0 just evaluates to false when x is a list and then you just get x out of it. When I run your code, the “actual” column show as zero.

2. Sam Hardwick

No, sorry, my mistake. It does work correctly with numpy arrays. It’s for some other reason that the plot shows incorrectly for me..

3. Sam Hardwick

Ah, I managed to break something in copy-pasting. Everything is correct, please ignore my comments.

4. Globules

Typo: all occurrences of “desk” should be “deck”. (Except this one.)

5. Jonathan Twite

I wonder how this would look if you used a more real-life shuffle simulation (eg. move a random number of cards from the top of the deck to the bottom of the deck (in the same order) a certain number of times)?

6. OK, I haven’t had enough coffee yet to allow myself to be persuaded of the Poisson-icity of this phenomenon. Can I get a hint?

7. Nice Python code, thanks. I always advocate Python for this purpose with all its libraries.

By the way, you do not need to shuffle two decks. Quite obviously, you just need to count the number of cards that keep place in a shuffled deck.

Here is the code in Euler Math Toolbox:

>nreps=1000000;
>dsize=52;
>matches=zeros(dsize+1);
>loop 1 to nreps; …
> k=sum(1:52==shuffle(1:52))+1; matches[k]=matches[k]+1; …
>end;
>matches=matches/nreps;
>i=0:7; columnsplot(matches[i+1],i); …