Impact factor for posts is a measurement of importance.

Impact factor for users reflect their authority, reputation and contribution on a particular topic.

Rating reflects the quality of posts.

Rating on Voofie is not a simple average of all ratings, but a weighted average of rating, weighted by the impact factor of users who rated.

Explore exciting communities of

Using Python to simulate Kruskal count and estimating the success probability

18 Apr 10

In this article, the programming language python will be used to estimate the success probability of the Kruskal Count.

Bookmark and Share

Content

Introduction

If you have no idea what Kruskal count is, please refer to: A simple to learn magic with amazing effect, The Kruskal Count. I will be using Python to simulate the trick. By doing the trick many times, and counting the number of success over all the trials, I can estimate the success probabiliy.
 

The Procedure

To calculate the success probability, we will first generate a random permutation of 52 cards. For each of the 1 to 10 secret number, we will do a Kruskal count, and see which card is the last selected card. For instance:

Table of secret no. and the final selected card
Secret number Last card
1 ♥ 10
2 ♥ 10
3 ♥ 10
4 ♥ 10
5 ♥ 10
6 ♥ 10
7 ♣ 2
8 ♣ 2
9 ♣ 2
10 ♥ 10

How do we calculate the success probability in this case?

\f$P(success) = P(\text{magician and audience selecting \{1,2,3,4,5,6,10\}}) + P(\text{magician and audience selecting \{7,8,9\}})\f$

\f$\Rightarrow P(success) = \left( \frac{7}{10} \right) ^2 + \left( \frac{3}{10} \right) ^2 \f$

\f$\Rightarrow P(success) = \frac{29}{50}\f$

The Code

kruskal.py

import random

def shuffle(x):
z = []
y = x[:]
for i in reversed(range(len(x))):
z.append(y.pop(random.randint(0, i)))
return z

def incremental(x):
r = x % 13
if 12 >= r >= 10:
return 5
else:
return r + 1

def percent(x):
a = {}
for j in x:
if j in a:
a[j]+=1
else:
a[j]= 1
p = 0
for y in a.values():
p += y**2
return p / float(len(x)**2)

def mean(x):
total = 0
for i in x:
total += i
return total / float(len(x))

def main(n):
pl = []
unsuffled_decks = range(52)
r10 = range(10)
results = [-1 for x in r10]
for k in range(n):
decks = shuffle(unsuffled_decks)
for i in r10:
c = i
while c < 52:
s = decks[c]
c += incremental(s)
results[i] = s
if (k % 10000 == 0):
print 'pass: %i' % k
pl.append(percent(results))
return pl

print mean(main(1000000))

I will explain what each of the function is doing.

shuffle(x):

def shuffle(x):
z = []
y = x[:]
for i in reversed(range(len(x))):
z.append(y.pop(random.randint(0, i)))
return z

The argument x is a list of different objects. And the function shuffle(x) will return a new list, which is a random permutation of the list x. Please notice that though in random package, there is a function called random.shuffle. We won't be using it since according to the documentation, even for small size x, most permutations can never be generated.

Basically, we first copy the list x to list y, so that we can change the list y without affecting the original list. Then we will randomly pick an element from y, and remove it using y.pop function, and put it in a new list z. We continue until all the element in y is removed, and added to z. z is a random permutation of the original list x.

incremental(x):

def incremental(x):
r = x % 13
if 12 >= r >= 10:
return 5
else:
return r + 1

To explain this function, I need to explain how we are going to represent the deck in the program. We will be using [0,1,2,..,51] to represent the whole 52 cards-deck, and each card is represented by a number ranged from 0 to 51. For instance:

  • ♠ 1 => 0
  • ♠ 2 => 1
  • ....
  • ♠ K => 12
  • ♥ 1 => 13
  • ....

The suit is not important in this case, since the we only need the face value of the card. As mentioned in A simple to learn magic with amazing effect, The Kruskal Count, all picture cards have value of 5, and other have their face value. The incremental(x) function is used to calculate the value of each card. We first do a modulo 13 of the card value x. If it's value is from 0 to 9, it's face value is the value plus 1. If the modulo value is 10 to 12, it means it is a picture cards, and should have a value of 5.

main(n):

def main(n):
pl = []
unsuffled_decks = range(52)
r10 = range(10)
results = [-1 for x in r10]
for k in range(n):
decks = shuffle(unsuffled_decks)
for i in r10:
c = i
while c < 52:
s = decks[c]
c += incremental(s)
results[i] = s
if (k % 10000 == 0):
print 'pass: %i' % k
pl.append(percent(results))
return pl

In this function, it will run the Kruskal Count and compute the success probability for n times, and then return a list of the success probability.

The variable pl is used to store the probability list. And the variable results is a list of 10 items, and they stored the ending card for the choice of 1 to 10 secret numbers.

The main loop:

        decks = shuffle(unsuffled_decks)
for i in r10:
c = i
while c < 52:
s = decks[c]
c += incremental(s)
results[i] = s

First of all, we shuffle the unsuffled_decks using the shuffe(x) function. Then for each of the secret number from 1 to 10, we set the current index c to the secret number first. Then while the current index c doesn't excess the number of card (since we counted from zero, so the condition is less than 52),  we put the current card decks[c] to the variable s. Then c is increased by the value of the card computed by the incremental(s) function. Once the current index excess 52, the loop ended, and we put the final card s into the results list.

After we get the final cards for all secret numbers, I will compute the success probability using percent(results), and append the probability to the pl list.

Since we are computing the probability by simulation, we need to repeat the experiment many times, in order to obtain a reliable result.

Result

You can copy and paste the code to a file named kruskal.py and run it. Here is the output:

pass: 0
pass: 10000
pass: 20000
pass: 30000
pass: 40000
pass: 50000
...
pass: 970000
pass: 980000
pass: 990000
0.84181804

So the success probability is found to be 0.84181804. So, if you as magician chooses a secret number randomly and do the Kruskal Count as the audience, you will have 84.18% of ending up with the same ending card as the audience.

If you wanted to calculated the result instead of doing simulation, you can refer to another post of mine which detailed the formulation of the problem, and how to solve it using programming technique.

0 Comments

Please login to post comment.

What is Voofie?

Voofie organizes knowledge, discovers useful resources and recognizes knowledgable users.

Bookmark your blog in Voofie to get more traffic as well as building a reputation in your field!

Explore more about it. Become a member—our FREE Registration takes just seconds.

Page Info
37Impacts
5/1 rate
1180
Your Rating:
Version: 2
Last update: 18 Apr 10
History Permalink
Author
Avatar for ross_tang

Ross Tang (ross_tang)

Degree in Physics and Mathematics, Master in Physics
香港

  • Probability
  • 312
  • Python (programming language)
  • 186
  • Computer simulation
  • 186