Skip to content

Instantly share code, notes, and snippets.

@seven1m
Created September 22, 2010 21:30
Show Gist options
  • Save seven1m/592622 to your computer and use it in GitHub Desktop.
Save seven1m/592622 to your computer and use it in GitHub Desktop.
require 'pp'
class Card
attr_reader :face_up
def initialize(face_up)
@face_up = face_up
end
def flip
@face_up ^= true
end
def inspect
"<Card #{face_up ? 'Up' : 'Down'}>"
end
end
def trick
deck = (
(1..42).map { Card.new(false) } +
(1..10).map { Card.new(true) }
).sort_by { rand }
new_deck = deck.pop(10)
new_deck.each { |c| c.flip }
deck_face_up_count = deck.count { |c| c.face_up }
new_deck_face_up_count = new_deck.count { |c| c.face_up }
[deck_face_up_count, new_deck_face_up_count]
end
counts = {}
100000.times do
c1, c2 = trick
if c1 != c2
puts "Error! #{c1} != #{c2}"
end
counts[c1] ||= 0
counts[c1] += 1
end
counts.sort.each do |num, count|
puts "#{num} => #{count}"
end
@alanhogan
Copy link

Lovely little script.

I ran with: ruby card_trick.rb | grep 'face up' a few times to see, on average, how many cards would be face up in each pile… I haven’t seen fewer than 6 yet.

@seven1m
Copy link
Author

seven1m commented Sep 22, 2010

You're right. I'm sure it's due to the way I "shuffled" the deck. No more than 4 of the face up cards have a chance to move up to the start of the deck. Then 10 get pulled off the bottom.

Need a better shuffling mechanism. :-)

@seven1m
Copy link
Author

seven1m commented Sep 22, 2010

Apparently lots of people use the sort rand technique I used, but sure enough it doesn't really randomize the array properly. I cannot seem to find a bit of Ruby on the interwebs that does the trick.

Weird.

@alanhogan
Copy link

I’m not so sure the shuffle is broken — the chances of the final count of each deck being 0 are extremely rare, rarer even than a royal flush.

@alanhogan
Copy link

That said, the shuffle algorithm does seem like it could be influenced quite a bit by the initial sort order?

@seven1m
Copy link
Author

seven1m commented Sep 23, 2010

Yes, it is. I cannot find a good shuffle function in Ruby. Even if I shuffle the deck 3 or 10 times or whatever, it still won't go below 6.

@sophiebits
Copy link

The easiest way to shuffle an array correctly in Ruby is to just sort_by { rand }.

@seven1m
Copy link
Author

seven1m commented Sep 23, 2010

Yeah, I tried that too. The array is not sufficiently randomized. Try it and see for your self -- the output of the script will never be less than 6.

@sophiebits
Copy link

I'm with alanhogan here; it's not a problem that you're not seeing any smaller numbers.

The probability that the output is less than 6 is only 1.51%, because for the output to be less than 6, more than 4 of the 10 face-up cards have to be in the first ten slots in the deck, which is incredibly unlikely.

(Probability is 541381/35791910, from Sum[Binomial[10, i] Binomial[42, 10 - i], {i, 5, 10}]/Binomial[52, 10] in Mathematica.)

@seven1m
Copy link
Author

seven1m commented Sep 23, 2010

Ahh, I see. You are right. I updated the script to show me a spread of the face-up card count. Here is the output from 100,000 runs of the trick:

2 => 1
3 => 9
4 => 163
5 => 1388
6 => 6964
7 => 20590
8 => 33551
9 => 28064
10 => 9270

Seems it's most likely that 8 cards are face-up in each pile at the end of the trick. Cool stuff!

@sophiebits
Copy link

Here is the theoretical distribution of probability:

0 => 6.3211 × 10^-11
1 => 2.65486 × 10^-8
2 => 2.44911 × 10^-6
3 => 0.0000870795
4 => 0.00148579
5 => 0.0135504
6 => 0.0696342
7 => 0.204639
8 => 0.335736
9 => 0.281853
10 => 0.0930114

You're right, 8 is the most common.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment