Я только что сделал программу, которая создает колоду из 26 карт, разбивает ее на 5 рук по 5 карт (отбрасывая 1) и проверяет покерные комбинации, которые есть в этих руках, если они есть.
Теперь я также сделал еще одну программу, которая зацикливается на этом, пока не будет найден флеш-рояль (что очень редко и должно происходить в среднем один раз каждые 600 000 или около того колод).
И что странно, как только я добавил счетчик, чтобы показать, сколько колод он прошел, он показывал только 150 - 4000! И я думаю, что это вина случайного перемешивателя. Я сделал аналогичную программу на Python, и она проверяла примерно правильное количество колод.
Я использовал это, что должно перетасовать колоду на месте:
fn shuffle_deck(deck: &mut Vec<Card>) -> () {
deck.shuffle(&mut rand::thread_rng())
}
Судя по всему, он не очень хорошо справляется со случайностью. Может ли кто-нибудь помочь мне найти лучшее решение?
Обновлено: также, для тех, кто интересуется, это структура карты:
pub struct Card {
value: i32,
suit: String
}
Это далеко не 1: 600k с колодой из 26 карт, 26 C 5 - это 65780, а в колоде 4 флеша-рояля, поэтому шансы на то, что любая данная рука окажется флеш-роялем, составляет 1: 16445. И поскольку вы видите 5 раздач за сессию, я бы предположил, что это 1:3289.
Я голосую за то, чтобы закрыть этот вопрос, потому что заявленная «проблема» на самом деле является правильным поведением.
Ваше предположение неверно.
26 карт могут составлять 26 over 5
возможных комбинаций, то есть 65780
комбинаций.
Поскольку у вас в колоде 4 флеш-рояля, вероятность того, что вам выпадет флеш-рояль, составляет 4/65780 = 0.006080875646093037 %
или один из всех 16445
.
Если вы посмотрите на четыре одновременно, это число примерно делится на 4 (не совсем потому, что эти четыре розыгрыша не являются независимыми), поэтому вы должны получать что-то примерно одно каждые ~3300
.
Итак, если вы измерите это экспериментально, вы получите:
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)
Что примерно соответствует ожидаемому. Таким образом, ваше предположение о том, что вы должны получать только один флеш-рояль каждый 600k
, неверно, и, скорее всего, что-то не так с вашим кодом на Python.
Тем не менее, если вы вычислите вероятность собрать один флеш-рояль в колоде из 52 карт, то вы должны получить (52 over 5) / 4
= один каждые 649740
розыгрышей. Вероятно, вы имели в виду, и если вы запрограммируете его, он соответствует его ожиданиям:
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)
"создает колоду из 26 карт" Как? Можете ли вы показать код? Кроме того, как вы получили число 1: 600k, похоже, это число для колод из 52 карт и недействительно для колод из 26 карт. Это также вероятность того, что одна конкретная рука окажется флеш-роялем, а не любая из рук. Лучше всего предоставить минимальный воспроизводимый пример.