Hi, proud2bBot.
Thanks for replying. I found some information in this thread: https://poker-ai.org/archive/www.pokerai.org/pf3/viewtopic3c0f.html?f=3&t=2881&hilit=. Kevin says there that 55190538 is the number of turn combinations "taking into account only suit isomorphisms". MegaZhiraf later replies to this that this number is actually is wrong.
I am not 100% sure what "taking into account only suit isomorphisms" means. But I am starting to feel that 55190538 is actually GREATER than the "number of canonical card combinations from one player's point of view" - the term used in the tech report.
I have put together a piece of C++ code that counts turn combinations. It reprocuces the number from the article - 55190538. But imagine the turn board is AcKcQc2d (on turn the new public card was 2d). This code will treat the following two hands as different: AdAh, AhAs. But I believe they are strategically the same, after flop the diamond suit had no chance of becoming a flush. So (if I haven't made an error in my reasoning) they should have defined properly what they mean by "canonical combinations".
Code:
int CountUniqueTurnHands( int (&flopMask)[4], int (&turnMask)[4] )
{
int result = 0;
for( int c1 = 0; c1 + 1 < 52; ++c1 )
{
if( turnMask[c1 % 4] & (1 << (c1 / 4)) ) // card is already on the board
continue;
for( int c2 = c1 + 1; c2 < 52; ++c2 )
{
if( turnMask[c2 % 4] & (1 << (c2 / 4)) )
continue;
bool isDuplicate = false;
for( int c1x = 0; c1x <= c1; ++c1x )
{
if( turnMask[c1x % 4] & (1 << (c1x / 4)) )
continue;
for( int c2x = c1x + 1; c2x < 52; ++c2x )
{
if( c1 == c1x && c2x >= c2 ) // we only check lexicographically preceding hands
continue;
if( turnMask[c2x % 4] & (1 << (c2x / 4)) )
continue;
// hands must have the same suited-ness
if( ((c1%4)==(c2%4)) && ((c1x%4)!=(c2x%4)) )
continue;
if( ((c1%4)!=(c2%4)) && ((c1x%4)==(c2x%4)) )
continue;
// checking if (c1, c2) is equivalent to (c1x, c2x) or to (c2x, c1x)
if( (c1/4 == c1x/4) && (flopMask[c1%4]==flopMask[c1x%4]) && (turnMask[c1%4]==turnMask[c1x%4]) && (c2/4 == c2x/4) && (flopMask[c2%4]==flopMask[c2x%4]) && (turnMask[c2%4]==turnMask[c2x%4]))
isDuplicate = true;
if( (c1/4 == c2x/4) && (flopMask[c1%4]==flopMask[c2x%4]) && (turnMask[c1%4]==turnMask[c2x%4]) && (c2/4 == c1x/4) && (flopMask[c2%4]==flopMask[c1x%4]) && (turnMask[c2%4]==turnMask[c1x%4]))
isDuplicate = true;
}
}
if( !isDuplicate )
++result;
}
}
return result;
}
void CountTurnCombinationsTurnPart( int& result, int (&flopMask)[4] )
{
int turnMask[4] = { flopMask[0], flopMask[1], flopMask[2], flopMask[3] };
for( int i = 0; i < 4; ++i )
{
bool skipSuit = false;
for ( int j = 0; j < i; ++j ) // checking if there is another suit with exactly the same cards
skipSuit = skipSuit || ( flopMask[i] == flopMask[j] );
if( skipSuit )
continue;
for( int j = 0; j < 13; ++j )
{
if( (flopMask[i] & (1 << j)) != 0 ) // if there already is a card with rank j
continue;
turnMask[i] |= ( 1 << j ); // adding the 4th card to the mask
result += CountUniqueTurnHands( flopMask, turnMask );
turnMask[i] ^= ( 1 << j ); // removing the 4th card
}
}
}
void CountTurnCombinationsFlopPart( int& result )
{
int mask[4] = {0};
for( int c1 = 0; c1 + 2 < 52; ++c1 )
{
mask[c1%4] |= ( 1 << (c1/4) );
for( int c2 = c1 + 1; c2 + 1 < 52; ++c2 )
{
mask[c2%4] |= ( 1 << (c2/4) );
for( int c3 = c2 + 1; c3 < 52; ++c3 )
{
mask[c3%4] |= ( 1 << (c3/4) );
if( mask[0] >= mask[1] && mask[1] >= mask[2] && mask[2] >= mask[3] )
CountTurnCombinationsTurnPart( result, mask );
mask[c3%4] ^= ( 1 << (c3/4) );
}
mask[c2%4] ^= ( 1 << (c2/4) );
}
mask[c1%4] ^= ( 1 << (c1/4) );
}
}
int main()
{
int n = 0;
CountTurnCombinationsFlopPart(n);
std::cout << n << "\n";
return 0;
}
Statistics: Posted by alex — Wed Apr 10, 2013 9:28 am
]]>