-
-
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 |
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. :-)
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.
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.
That said, the shuffle algorithm does seem like it could be influenced quite a bit by the initial sort order?
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.
The easiest way to shuffle an array correctly in Ruby is to just sort_by { rand }
.
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.
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.)
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!
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.
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.