In (this) Poker you have 2 hole cards that are combined with 5 shared cards on the board. Each player makes the best 5 card hand from the seven. Believe it or not that is over 2 billion runs to do them all.
I'm trying to create statistics for 2 known hole cards against random boards and random hands for a single opponent using Monte Carlo for like 20 million runs.
First get sets of 7 random for board plus 1 opponent from 50 (known 2 hole cards are removed). From those 7 remove all 2 card combinations (21) to represent the opponent's hole cards. The idea is better statistics with an exhaustive examination of the 7 rather than a random 5 and a random 2. Computation on the random 5 plus random 2 is more efficient as you only need to run the known hand once for each random 5.
byte? skip1 = null;
byte? skip2 = null;
List<byte> deck50seven = null;
byte nextSevenLastStart = 42;
private IEnumerable<byte> NextSevenA(byte Skip1, byte Skip2)
{
if (Skip1 == Skip2)
throw new ArgumentOutOfRangeException("skip1 == skip2");
if (Skip1 > 51 || Skip2 > 51 || Skip1 < 0 || Skip2 < 0)
throw new ArgumentOutOfRangeException("51 0");
if(skip1 == null)
{
skip1 = Skip1;
skip2 = Skip2;
deck50seven = new List<byte>(50);
for(byte b = 0; b < 52; b++)
{
if (b == Skip1 || b == Skip2)
continue;
deck50seven.Add(b);
}
}
else
{
if (Skip1 != skip1 || Skip2 != skip2)
throw new ArgumentException("skippy");
}
if (nextSevenLastStart >= 42)
{
nextSevenLastStart = 0;
// Yates shuffle
for (int i = 49; i >= 1; i--)
{ // int for indexing is faster (I think)
int j = rand.Next(i + 1); // it can get swapped with itself
if (j != i)
{ // exchange values
byte curVal = deck50seven[i];
deck50seven[i] = deck50seven[j];
deck50seven[j] = curVal;
}
}
}
else
nextSevenLastStart += 7;
return deck50seven.GetRange(nextSevenLastStart, 7);
}
private IEnumerable<List<byte>> NextSevenAsFiveTwo(List<byte> input)
{
// 21 ways to take 2 from 7
// this is going to seem strange but need every combination of 2 to be the last 2
if (input.Count() != 7)
throw new ArgumentOutOfRangeException("input.Count() != 7");
List<byte> output = new List<byte>();
for (byte i = 0; i <= 5; i++)
{
for (byte j = (byte)(i + 1); j <= 6; j++)
{
output.Clear();
for (byte k = 0; k < 7; k++)
if (k != i && k != j)
output.Add(input[k]);
output.Add(input[i]);
output.Add(input[j]);
yield return output;
}
}
}
can use this for test
for (int i = 0; i < 10; i++)
{
List<byte> nextSevenA = new List<byte>(NextSevenA(11, 12));
Debug.WriteLine("Base " + string.Join(", ", nextSevenA));
foreach(List<byte> ss in NextSevenAsFiveTwo(nextSevenA))
Debug.WriteLine(" Subset " + string.Join(", ", ss));
}