Poker is 52 cards - 4 suite and 13 rank:
- Hand is exaclty 5 cards
- Order of hands
- Straight-flush - all same suite and in order
- Quad four of same rank
- Boat three of one rank and two of another rank
- Straight e.g. 56789
Ace 0 counts as both low and high 01234 and 9,10,11,12,0 - Two pair
- One pair
- High card
This code gives the correct answers to Poker hand probability.
There are 2,598,960 distinct 5 card hands in a deck of 52. I am not interested in a random sampling (Monte Carlo).
Can it be made faster? Right now it runs in 4 seconds, and 2.5 of the 4 seconds is loading the Dictionary. The results of the Dictionary make tally of straight and same rank easy / fast. The raw loop with no hand evaluation is only 0.019 seconds. I know 4 seconds is fast but the next step is a situation where I need to do a very similar analysis millions of times.
// all the counts are the output
int counter = 0;
int counterFlush = 0;
int counterStraight = 0;
int counterStraightFlush = 0;
int counterQuad = 0;
int counterBoat = 0;
int counterTrips = 0;
int counterPairTwo = 0;
int counterPairOne = 0;
int counterHigh = 0;
// end output
Dictionary<int, int> rankCount = new Dictionary<int,int>(5);
int card1rank;
int card1suit;
int card2rank;
int card2suit;
int card3rank;
int card3suit;
int card4rank;
int card4suit;
int card5rank;
int card5suit;
bool haveStraight;
bool haveFlush;
for(int i = 51; i >= 4; i--)
{
card1rank = i % 13;
card1suit = i / 13;
for (int j = i - 1; j >= 3; j--)
{
card2rank = j % 13;
card2suit = j / 13;
for (int k = j - 1; k >= 2; k--)
{
card3rank = k % 13;
card3suit = k / 13;
for (int l = k - 1; l >= 1; l--)
{
card4rank = l % 13;
card4suit = l / 13;
for (int m = l - 1; m >= 0; m--)
{
counter++;
//if (rand.Next(4) != 0)
// continue;
haveStraight = false;
haveFlush = false;
card5rank = m % 13;
card5suit = m / 13;
if (card1suit == card2suit && card1suit == card3suit && card1suit == card4suit && card1suit == card5suit)
{
haveFlush = true;
}
rankCount.Clear();
rankCount.Add(card1rank, 1);
if (rankCount.ContainsKey(card2rank))
rankCount[card2rank]++;
else
rankCount.Add(card2rank, 1);
if (rankCount.ContainsKey(card3rank))
rankCount[card3rank]++;
else
rankCount.Add(card3rank, 1);
if (rankCount.ContainsKey(card4rank))
rankCount[card4rank]++;
else
rankCount.Add(card4rank, 1);
if (rankCount.ContainsKey(card5rank))
rankCount[card5rank]++;
else
rankCount.Add(card5rank, 1);
//continue;
if (rankCount.Count == 5)
{ // can only have a straight if the count is 5
if (rankCount.Keys.Max() - rankCount.Keys.Min() == 4)
{
haveStraight = true;
}
else if (rankCount.Keys.Min() == 0 && rankCount.Keys.Max() == 12)
{ // possible ace high straight
if (rankCount.Keys.OrderBy(x => x).FirstOrDefault(x => x > 0) == 9)
{
haveStraight = true;
}
}
}
if (haveStraight && haveFlush)
counterStraightFlush++;
else if (haveFlush)
counterFlush++;
else if (haveStraight)
counterStraight++;
else if (rankCount.Count == 5)
counterHigh++; // cannot have and pairs if the count is 5
else
{
bool quap = false;
bool trips = false;
int pair = 0;
foreach (KeyValuePair<int, int> kvp in rankCount.OrderByDescending(x => x.Value))
{
if (kvp.Value == 4)
quap = true;
else if (kvp.Value == 3)
trips = true;
else if (kvp.Value == 2)
pair++;
}
if (quap)
counterQuad++;
else if (trips)
{
if (pair > 0)
counterBoat++;
else
counterTrips++;
}
else if (pair == 2)
counterPairTwo++;
else if (pair == 1)
counterPairOne++;
else
counterHigh++; // should not actually get here
}
}
}
}
}
}