The ‘Magic’ of Kruskal’s Card Count

Some magic tricks rely on misdirection, getting your audience to focus on something while the trick is actually happening somewhere else. Other tricks involve the magician taking advantage of not-commonly understood occurrences based on mathematical or scientific principles. Like, watch this small, metal object attach itself to another small, metal object! Magnets, how do they work?!

OK, most people won’t fall for that. But here’s a trick involving a deck cards that might stump your friends. Originally invented by mathematician Martin Kruskal, John Allen Paulos wrote about it in his book Once Upon a Number: the Hidden Mathematical Logic of Stories:

Imagine two players, Tricked and Trickster. Trickster asks Tricked to pick a secret number — say X — between 1 and 10, and goes on to instruct Tricked to watch for the Xth card as Trickster slowly and one by one turns over the cards in a well-shuffled deck. When the Xth card is reached — say it’s a Y — it becomes Tricked’s new secret number and he is asked to watch for the Yth succeeding card after it as Trickster continues to slowly turn over cards one by one.

Every time Tricked’s secret number is reached, that card becomes the new secret number until Trickster gets to the end of the deck. (Note: There are variations to the trick when it comes to handling face cards, but let’s say face cards and aces are represented by the number of letters in their name. So, for example, an “ace” is worth a 3.) As the Trickster nears the end of the deck, he/she (“almost always” as Paulos points out) successfully guesses Tricked’s secret number.

What’s the secret? At the beginning of the trick, Trickster also picks a secret number between 1-10 and does exactly what Tricked does as the cards are flipped. Through the magic of probability, the paths of both the Trickster and Tricked almost always align. (Note: I’m not going to go through the math here, but you’ll find a simple explanation here and a more complicated explanation here.)

Here’s a better look at the process, where Trickster picks a 3 and Tricked picks a 4 (in the version Paulos describes, the face cards are omitted):

Kruskal's Card Count

And here is the trick recreated in R (with face cards included). First we take a deck and shuffle it.

# deck
deck <- c(rep(2:10,4),
          # handling face cards
          rep(nchar("king"),4),
          rep(nchar("queen"),4),
          rep(nchar("jack"),4),
          rep(nchar("ace"),4))

# shuffle the deck
set.seed(200)
shuffled.deck <- sample(deck,52, replace=F)

shuffled.deck
##  [1]  2  4  3  8  7  4  4  6  7  3  3 10  8  9  7  4  4  4  6  5  4  5  4
## [24]  5 10  9  2  2  2  4  7  5  8  3  9  5  4  3  4  6  3  6  5  3  5  9
## [47]  5  8 10 10  4  3

Then Trickster and Tricked pick numbers.

## [1] "Trickster's secret number is 4"
## [1] "Tricked's secret number is 3"

Now we run through the shuffled deck.

## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 8"
## [1] "Tricked's secret number is now 3"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 10"
## [1] "Tricked's secret number is now 4"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 5"
## [1] "Tricked's secret number is now 3"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 2"
## [1] "Tricked's secret number is now 8"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 2"
## [1] "Tricked's secret number is now 4"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 7"
## [1] "Tricked's secret number is now 10"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 3"
## [1] "Tricked's secret number is now 9"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 3"
## [1] "Tricked's secret number is now 3"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 3"
## [1] "Tricked's secret number is now 5"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 5"
## [1] "Tricked's secret number is now 3"
## [1] "Cards are flipped"
## [1] "Trickster's secret number is now 3"
## [1] "End of Deck"

By the end of the deck, both Trickster and Tricked have ended up on 3, the very last card. As Paulos’ quote above suggested, the trick doesn’t always work. In the simulation in R, I chose to include face cards because the more cards in the deck, the higher the probability you and your audience will land on the same card toward the end.

Improving Your Chances

I wrote a function in R that simulates the trick (like I did above) but takes in whether you want to include face cards (TRUE or FALSE) and the number of decks as arguments. The function outputs whether Trickster and Tricked’s last numbers are equal.

simulate.trick <- function(face=TRUE, decks=1) {
  
  deck <- c(rep(2:10,4))
  
  if(face==T){
    deck <- c(deck,
            rep(nchar("king"),4),
            rep(nchar("queen"),4),
            rep(nchar("jack"),4),
            rep(nchar("ace"),4))

    num.cards <- length(deck)
    shuffled.deck <- sample(deck,num.cards, replace=F)
    
  } else { 
    num.cards <- length(deck)
    shuffled.deck <- sample(deck,num.cards, replace=F) }
  
  if(decks > 1) { 
    x <- 2
    while(x <= decks) {
      shuffled.deck <- c(shuffled.deck, sample(shuffled.deck,num.cards,replace = F))
      x <- x + 1
    }
  }

  trickster <- sample(1:10,1)
  tricked <- sample(1:10,1)
  trickster.pos <- c(trickster)
  tricked.pos <- c(tricked)
  
  x <- 2
  
  while(x < length(shuffled.deck)) {
    if(!is.na(shuffled.deck[sum(trickster.pos)])) {
      trickster.pos <- c(trickster.pos, shuffled.deck[sum(trickster.pos)])
    } else {  }
    if(!is.na(shuffled.deck[sum(tricked.pos)])) {  
      tricked.pos <- c(tricked.pos, shuffled.deck[sum(tricked.pos)])
    } else {  }
    x <- x+1 
  }
  
  ifelse(tail(tricked.pos,1) == tail(trickster.pos,1), TRUE, FALSE) 
  
}

Using the outcomes, I can test the probability of success for various scenarios.

  • One deck, no face cards: In 10,000 simulations, the trick was successful 68.4% of the time.
  • One deck, with face cards: In 10,000 simulations, the trick was successful 85.43% of the time.
  • Two decks, with face cards: In 10,000 simulations, the trick was successful 98.04% of the time.

Is Random Too Random?

When running the simulations, I used R’s sample() function in order to shuffle the deck and choose Trickster and Tricked’s secret numbers. People are not as random as R.

While Trickster has a \(\frac{1}{10}\) chance of guessing the exact same number as Tricked, there are experiments out there that have shown most people will pick the number 7 when asked to choose a number between 1 and 10. Why? Maybe it’s because 7 is considered by some to be a lucky number. Or maybe it’s because 7 is a common number in the Bible and people are superstitious. Who knows.

All you need to know is that picking the number 7 is yet another way to increase the trick’s probability of success.

Now go blow some minds.