I just made a program that creates a deck with 26 cards, splits it into 5 hands of 5 cards (discarding 1) and checks the poker combinations that are in those hands, if any.
Now, I also made another program that loops over this until a Royal Flush is found (which is very rare and should happen, on average, once every 600k or so decks).
And the strange thing is, once I added a counter to show how many decks it went through, it only said 150 - 4000 ! And I think it's the random shuffler's fault. I had made a similar program in Python, and that was checking approximately the correct amount of decks.
I used this, which should shuffle the deck in place:
fn shuffle_deck(deck: &mut Vec<Card>) -> () {
deck.shuffle(&mut rand::thread_rng())
}
Apparently, it's not doing a very good job at being random. Can anybody help me in finding a better solution?
Edit: also, for anyone wondering, this is the Card struct:
pub struct Card {
value: i32,
suit: String
}
Your assumption is incorrect.
26 cards can make 26 over 5
possible combinations, which is 65780
combinations.
As you have 4 royal flushes in your deck, the probability to get dealt a royal flush is 4/65780 = 0.006080875646093037 %
or one out of ever 16445
.
If you look at four at a time, this number roughly divides by 4 (not exactly because those four draws aren't independent), so you should get something in the ballpark of one every ~3300
.
So if you measure it experimentally, you get:
use rand::seq::SliceRandom;
fn is_royal_flush(deck: &[u8]) -> bool {
if deck.len() != 5 {
false
} else {
let mut buckets = [0u8; 4];
for el in deck {
if let Some(bucket) = buckets.get_mut((*el / 5) as usize) {
*bucket += 1;
}
}
buckets.iter().any(|bucket| *bucket == 5)
}
}
fn has_royal_flush(deck: &[u8; 26]) -> bool {
is_royal_flush(&deck[0..5])
|| is_royal_flush(&deck[5..10])
|| is_royal_flush(&deck[10..15])
|| is_royal_flush(&deck[15..20])
|| is_royal_flush(&deck[20..25])
}
fn main() {
let mut rng = rand::thread_rng();
let mut deck = [0; 26];
deck.iter_mut()
.enumerate()
.for_each(|(pos, val)| *val = pos as u8);
println!("Deck, initially: {:?}", deck);
deck.shuffle(&mut rng);
println!("Deck, shuffled: {:?}", deck);
println!();
let mut total: usize = 0;
let mut royal_flushes: usize = 0;
loop {
deck.shuffle(&mut rng);
total += 1;
if has_royal_flush(&deck) {
royal_flushes += 1;
}
if total % 10000000 == 0 {
println!(
"Now {} out of {}. (Probability: 1/{})",
royal_flushes,
total,
total / royal_flushes
);
}
}
}
Deck, initially: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
Deck, shuffled: [25, 16, 3, 12, 18, 1, 14, 8, 17, 0, 5, 15, 6, 11, 4, 21, 2, 13, 24, 20, 22, 7, 10, 9, 19, 23]
Now 2976 out of 10000000. (Probability: 1/3360)
Now 6004 out of 20000000. (Probability: 1/3331)
Now 8973 out of 30000000. (Probability: 1/3343)
Now 11984 out of 40000000. (Probability: 1/3337)
Which is roughly in the expected ballpark. So your assumption is off that you should get only one royal flush every 600k
, and most likely something is wrong with your python code.
That said, if you compute the probability to get a single royal flush in a 52 card deck, then you should get (52 over 5) / 4
= one every 649740
draws. Which is probably what you were referring to, and if you program it, it matches its expectations:
use rand::seq::SliceRandom;
fn is_royal_flush(deck: &[u8]) -> bool {
if deck.len() != 5 {
false
} else {
let mut buckets = [0u8; 4];
for el in deck {
if let Some(bucket) = buckets.get_mut((*el / 5) as usize) {
*bucket += 1;
}
}
buckets.iter().any(|bucket| *bucket == 5)
}
}
fn has_royal_flush(deck: &[u8; 52]) -> bool {
is_royal_flush(&deck[0..5])
}
fn main() {
let mut rng = rand::thread_rng();
let mut deck = [0; 52];
deck.iter_mut()
.enumerate()
.for_each(|(pos, val)| *val = pos as u8);
println!("Deck, initially: {:?}", deck);
deck.shuffle(&mut rng);
println!("Deck, shuffled: {:?}", deck);
println!();
let mut total: usize = 0;
let mut royal_flushes: usize = 0;
loop {
deck.shuffle(&mut rng);
total += 1;
if has_royal_flush(&deck) {
royal_flushes += 1;
}
if total % 10000000 == 0 {
println!(
"Now {} out of {}. (Probability: 1/{})",
royal_flushes,
total,
total / royal_flushes
);
}
}
}
Deck, initially: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]
Deck, shuffled: [2, 15, 44, 39, 26, 47, 28, 11, 1, 19, 31, 6, 43, 42, 29, 48, 35, 30, 3, 49, 50, 37, 9, 10, 18, 45, 33, 22, 36, 5, 38, 46, 51, 32, 7, 17, 23, 27, 41, 14, 21, 13, 25, 4, 8, 16, 20, 24, 12, 34, 0, 40]
Now 6 out of 10000000. (Probability: 1/1666666)
Now 22 out of 20000000. (Probability: 1/909090)
Now 36 out of 30000000. (Probability: 1/833333)
Now 54 out of 40000000. (Probability: 1/740740)
Now 70 out of 50000000. (Probability: 1/714285)
Now 78 out of 60000000. (Probability: 1/769230)
Now 92 out of 70000000. (Probability: 1/760869)
Now 102 out of 80000000. (Probability: 1/784313)
Now 125 out of 90000000. (Probability: 1/720000)
Now 139 out of 100000000. (Probability: 1/719424)
Now 164 out of 110000000. (Probability: 1/670731)
Now 190 out of 120000000. (Probability: 1/631578)
Now 202 out of 130000000. (Probability: 1/643564)
Now 217 out of 140000000. (Probability: 1/645161)
Now 232 out of 150000000. (Probability: 1/646551)
Now 248 out of 160000000. (Probability: 1/645161)