Two Plus Two Poker Forums PLO Hand Lookup program
 Register FAQ Search Today's Posts Mark Forums Read TwoPlusTwo.com

 Notices

 Yesterday, 10:25 AM #1 Steve journeyman     Join Date: Jan 2003 Location: Florida Posts: 270 PLO Hand Lookup program There are 270,725 (52C4) starting hands in Omaha, counting suits. I wrote a program that puts them all in a list. Hand #1: 2c 3c 4c 5c Hand #2: 2c 3c 4c 6c Hand #3: 2c 3c 4c 7c Hand #4: 2c 3c 4c 8c ………….etc Hand #48: 2c 3c 4c Ks Hand #49: 2c 3c 4c As Hand #50: 2c 3c 5c 6c Hand #51: 2c 3c 5c 7c ………….etc Hand #270722: Ts Js Qs As Hand #270723: Ts Js Ks As Hand #270724: Ts Qs Ks As Hand #270725: Js Qs Ks As Great. So now, how do we do the reverse? Given four random cards, such as (7d 8d Kh Ks) is there an elegant formula that will compute its hand number? I want to store some statistics for each hand in an array[270725] and then quickly look up a hand.
 Yesterday, 12:30 PM #2 RustyBrooks Carpal \'Tunnel     Join Date: Feb 2006 Location: Austin, TX Posts: 23,838 Re: PLO Hand Lookup program I feel like there has to be a way to do this, but I spent a little time this morning and came up fairly blank, in terms of a straightforward numeric algorithm Can you do me a favor and send me your hand list? I could generate it myself but it would save me some time. I have a few ideas. I assume you'll be using C/C++? If not I'd say just use a hashmap.
 Yesterday, 01:20 PM #3 Steve journeyman     Join Date: Jan 2003 Location: Florida Posts: 270 Re: PLO Hand Lookup program Here's the code, is that what you wanted? Or do you want a file with all 270725 hands in it? public function EnumerateOmahaHands() { var totalHands = 0; for (var c0 = 0; c0 < 1; c0++) { for (var c1 = c0+1; c1 < 50; c1++) { for (var c2 = c1+1; c2 < 51; c2++) { for (var c3 = c2+1; c3 < 52; c3++) { totalHands++; trace("HAND #" + totalHands + ": " + GetCard(c0) + " " + GetCard(c1) + " " + GetCard(c2) + " " + GetCard(c3)); } } } } } public function GetCard(card:Number) { var cardString = ""; var rankArray = "23456789TJQKA"; var suitArray = "cdhs"; cardString += rankArray.charAt(card % 13); cardString += suitArray.charAt(card / 13); return cardString; }
 Yesterday, 02:04 PM #4 jukofyork Carpal \'Tunnel     Join Date: Sep 2004 Location: Glastonbury Grove Posts: 11,314 Re: PLO Hand Lookup program Code: ```// First make a lookup table of all the 24 possible hand ordering permutations: int PERMS[24][4]={{0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1}, {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0}, {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, {3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}}; // Next we need a function to map an unordered 4-card hand to a unique integer. // NOTE: 140608=52^3, 2704=52^2, etc. int getIndex(int c0, int c1, int c2, int c3) { return c0*140608 + c1*2704 + c2*52 + c3; } // Next create a lookup table of size 52^4, which we will populate so as to map from unordered --> ordered index. int lookup[7311616]; // You can now populate this as you create your ordering: int handIndex=0; for (int c0 = 0; c0 < 49; c0++) { for (int c1 = c0+1; c1 < 50; c1++) { for (int c2 = c1+1; c2 < 51; c2++) { for (int c3 = c2+1; c3 < 52; c3++) { int hand[4]={c0, c1, c2, c3}; for (int i=0; i<24; i++) { lookup[getIndex(hand[PERMS[i][0]],hand[PERMS[i][1]],hand[PERMS[i][2]],hand[PERMS[i][3]])]=handIndex; } handIndex++; } } } } . . . // Now you can lookup your ordered hand index in O(1) from an unordered hand using: int handIndex=lookup[getIndex(c0,c1,c2,c3)];``` PS: Be careful if you copy my code exactly and write this in C/C++: putting a ~30MB array on the stack will cause a stack overflow! Either use "static int lookup[7311616];" or allocate it dynamically to ensure it goes on the heap. Juk Last edited by jukofyork; Yesterday at 02:19 PM.
Yesterday, 02:16 PM   #5
jukofyork
Carpal \'Tunnel

Join Date: Sep 2004
Location: Glastonbury Grove
Posts: 11,314
Re: PLO Hand Lookup program

Quote:
 Originally Posted by Steve Code: ```public function EnumerateOmahaHands() { var totalHands = 0; for (var c0 = 0; c0 < 1; c0++) { for (var c1 = c0+1; c1 < 50; c1++) { for (var c2 = c1+1; c2 < 51; c2++) { for (var c3 = c2+1; c3 < 52; c3++) { totalHands++; trace("HAND #" + totalHands + ": " + GetCard(c0) + " " + GetCard(c1) + " " + GetCard(c2) + " " + GetCard(c3)); } } } } }```
Surely that should be 49 or else you'll only generate hands starting with 2c?

Juk

Yesterday, 02:47 PM   #6
Steve
journeyman

Join Date: Jan 2003
Location: Florida
Posts: 270
Re: PLO Hand Lookup program

Quote:
 Originally Posted by jukofyork Surely that should be 49 or else you'll only generate hands starting with 2c? Juk
Yikes, sorry yep that's what I meant.

Yesterday, 02:51 PM   #7
Steve
journeyman

Join Date: Jan 2003
Location: Florida
Posts: 270
Re: PLO Hand Lookup program

Quote:
 Originally Posted by jukofyork Code: ```// First make a lookup table of all the 24 possible hand ordering permutations: int PERMS[24][4]={{0, 1, 2, 3}, {0, 1, 3, 2}, {0, 2, 1, 3}, {0, 2, 3, 1}, {0, 3, 1, 2}, {0, 3, 2, 1}, {1, 0, 2, 3}, {1, 0, 3, 2}, {1, 2, 0, 3}, {1, 2, 3, 0}, {1, 3, 0, 2}, {1, 3, 2, 0}, {2, 0, 1, 3}, {2, 0, 3, 1}, {2, 1, 0, 3}, {2, 1, 3, 0}, {2, 3, 0, 1}, {2, 3, 1, 0}, {3, 0, 1, 2}, {3, 0, 2, 1}, {3, 1, 0, 2}, {3, 1, 2, 0}, {3, 2, 0, 1}, {3, 2, 1, 0}}; // Next we need a function to map an unordered 4-card hand to a unique integer. // NOTE: 140608=52^3, 2704=52^2, etc. int getIndex(int c0, int c1, int c2, int c3) { return c0*140608 + c1*2704 + c2*52 + c3; } // Next create a lookup table of size 52^4, which we will populate so as to map from unordered --> ordered index. int lookup[7311616]; // You can now populate this as you create your ordering: int handIndex=0; for (int c0 = 0; c0 < 49; c0++) { for (int c1 = c0+1; c1 < 50; c1++) { for (int c2 = c1+1; c2 < 51; c2++) { for (int c3 = c2+1; c3 < 52; c3++) { int hand[4]={c0, c1, c2, c3}; for (int i=0; i<24; i++) { lookup[getIndex(hand[PERMS[i][0]],hand[PERMS[i][1]],hand[PERMS[i][2]],hand[PERMS[i][3]])]=handIndex; } handIndex++; } } } } . . . // Now you can lookup your ordered hand index in O(1) from an unordered hand using: int handIndex=lookup[getIndex(c0,c1,c2,c3)];``` PS: Be careful if you copy my code exactly and write this in C/C++: putting a ~30MB array on the stack will cause a stack overflow! Either use "static int lookup[7311616];" or allocate it dynamically to ensure it goes on the heap. Juk
Thanks Juk. I'm still hoping there is an elegant formula for looking up a hand# that doesn't involve creating this 7MB table in memory. This is going to be in a JavaScript poker tool and I was hoping to avoid creating that at runtime (or having to download 7MB). But, there may not be a formula.

 Yesterday, 03:19 PM #8 RustyBrooks Carpal \'Tunnel     Join Date: Feb 2006 Location: Austin, TX Posts: 23,838 Re: PLO Hand Lookup program yeah so if it's javascript I would just say use a hashmap instead of a numeric array
Yesterday, 05:18 PM   #9
jukofyork
Carpal \'Tunnel

Join Date: Sep 2004
Location: Glastonbury Grove
Posts: 11,314
Re: PLO Hand Lookup program

Quote:
 Originally Posted by Steve Thanks Juk. I'm still hoping there is an elegant formula for looking up a hand# that doesn't involve creating this 7MB table in memory. This is going to be in a JavaScript poker tool and I was hoping to avoid creating that at runtime (or having to download 7MB). But, there may not be a formula.
Here's a rough outline of a method that requires no lookup table (but is more costly per operation):

Given an unordered 4-tuple:

You first need sort it into ascending order. The most efficient method for this is to use a 4-element sorting network, eg:

Code:
```void sortInPlace(int& c0, int& c1, int& c2, int& c3) {
SWAP_IF_GREATER_THAN(c0,c2);
SWAP_IF_GREATER_THAN(c1,c3);
SWAP_IF_GREATER_THAN(c0,c1);
SWAP_IF_GREATER_THAN(c2,c3);
SWAP_IF_GREATER_THAN(c1,c2);
}```
Then you need to use the idea of combinadics to be able to directly generate a position in the lexicographic ordering, eg:

Code:
```int getHandIndex(int c0, int c1, int c2, int c3) {
return binomial(c0,1) + binomial(c1,2) + binomial(c2,3) + binomial(c3,4);
}```
So then you can get your hand index directly like so:

Code:
```sortInPlace(c0,c1,c2,c3);
int handIndex=getHandIndex(c0,c1,c2,c3);```
(you'll have to search for a javascript implementation of binomial(). In C++ you can use the boost library's binomial_coefficient() function - perhaps have a look at the source for that?)

Juk

Last edited by jukofyork; Yesterday at 05:30 PM.

Yesterday, 06:23 PM   #10
jukofyork
Carpal \'Tunnel

Join Date: Sep 2004
Location: Glastonbury Grove
Posts: 11,314
Re: PLO Hand Lookup program

Too late to edit now, but I just noticed that the code above doesn't actually generate the indices in the same order as your loops. From the wiki page:

Quote:
 So comparing the 5-combinations C = {0,3,4,6,9} and C' = {0,1,3,7,9}, one has that C comes before C', since they have the same largest part 9, but the next largest part 6 of C is less than the next largest part 7 of C'; the sequences compared lexicographically are (9,6,4,3,0) and (9,7,3,1,0)
I *think* this should generate the ordering in exactly the same way as your loops though:

Code:
```int getHandIndex(int c0, int c1, int c2, int c3) {
return 270724 - binomial(52-(c1+1),4) - binomial(52-(c2+1),3) - binomial(52-(c3+1),2) - binomial(52-(c4+1),1);
}```
Also, the "National Lottery example in Excel" example shows a slight optimisation as: binomial(52-(c4+1),1) = 51-c4

Code:
```int getHandIndex(int c0, int c1, int c2, int c3) {
return 270673 - binomial(52-(c1+1),4) - binomial(52-(c2+1),3) - binomial(52-(c3+1),2) + c4;
}```
Juk

Last edited by jukofyork; Yesterday at 06:28 PM.

 Yesterday, 07:04 PM #11 jukofyork Carpal \'Tunnel     Join Date: Sep 2004 Location: Glastonbury Grove Posts: 11,314 Re: PLO Hand Lookup program Courtesy of Mathematica's "simplify", here's the final function along with a small test driver: Code: ```#include // NOTE: Must have c0 < c1 < c2 < c3. int getHandIndex(int c0, int c1, int c2, int c3) { return (484902*c0 - 14699*c0*c0 + 198*c0*c0*c0 - c0*c0*c0*c0 + 4*(-7962 + 7499*c1 - 150*c1*c1 + c1*c1*c1 + 303*c2 - 3*c2*c2 + 6*c3))/24; } int main() { int handIndex=0; for (int c0 = 0; c0 < 49; c0++) { for (int c1 = c0+1; c1 < 50; c1++) { for (int c2 = c1+1; c2 < 51; c2++) { for (int c3 = c2+1; c3 < 52; c3++) { std::cout << handIndex << " = " << getHandIndex(c0,c1,c2,c3) << "\n"; handIndex++; } } } } }``` (just paste it into http://cpp.sh/ and hit "run") I'm not sure if I'd call it an "elegant formula" as the OP hoped for, but it does seem to work! Juk
Yesterday, 09:17 PM   #12
Steve
journeyman

Join Date: Jan 2003
Location: Florida
Posts: 270
Re: PLO Hand Lookup program

Quote:
 Originally Posted by jukofyork I'm not sure if I'd call it an "elegant formula" as the OP hoped for, but it does seem to work! Juk
THAT'S INCREDIBLE!

And yes, I call that elegant x 10^23

I'm reading up on the lottery example now. THANKS JUK!

Today, 07:30 AM   #13
jukofyork
Carpal \'Tunnel

Join Date: Sep 2004
Location: Glastonbury Grove
Posts: 11,314
Re: PLO Hand Lookup program

Quote:
 Originally Posted by Steve THAT'S INCREDIBLE! And yes, I call that elegant x 10^23 I'm reading up on the lottery example now. THANKS JUK!
NP

If you search google for 'site:twoplustwo.com combinadics' and 'site:twoplustwo.com "sorting network"' then you'll find some other posts I made (~10 years ago) about using this same method in the "7 Card Hand Evaluators" thread.

Juk

 Thread Tools Display Modes Linear Mode

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is Off Forum Rules
 Forum Jump User Control Panel Private Messages Subscriptions Who's Online Search Forums Forums Home Links to Popular Forums     News, Views, and Gossip     Beginners Questions     Marketplace & Staking     Casino & Cardroom Poker     Internet Poker     NL Strategy Forums     Poker Goals & Challenges     Las Vegas Lifestyle     Sporting Events     Politics     Other Other Topics Two Plus Two     About the Forums     Two Plus Two Magazine Forum     The Two Plus Two Bonus Program     Two Plus Two Pokercast     The Best of Two Plus Two Marketplace & Staking     Commercial Marketplace     General Marketplace     Staking - Offering Stakes     Staking         Staking - Offering Stakes         Staking - Seeking Stakes         Staking - Selling Shares - Online         Staking - Selling Shares - Live         Staking Rails         Transaction Feedback & Disputes     Transaction Feedback & Disputes Coaching & Training     Coaching Advice     Cash Game Poker Coach Listings     Tournament/SNG Poker Coach Listings Poker News & Discussion     News, Views, and Gossip     Poker Goals & Challenges     Poker Beats, Brags, and Variance     That's What She Said!     Poker Legislation & PPA Discussion hosted by Rich Muny     Twitch - Watch and Discuss Live Online Poker     Televised Poker General Poker Strategy     Beginners Questions     Books and Publications     Poker Tells/Behavior, hosted by: Zachary Elwood     Poker Theory     Psychology No Limit Hold'em Strategy     Medium-High Stakes PL/NL     Micro-Small Stakes PL/NL     Medium-High Stakes Full Ring     Micro-Small Stakes Full Ring     Heads Up NL     Live Low-stakes NL Limit Texas Hold'em Strategy     Mid-High Stakes Limit     Micro-Small Stakes Limit Tournament Poker Strategy     STT Strategy     Heads Up SNG and Spin and Gos     Mid-High Stakes MTT     Small Stakes MTT     MTT Community     Tournament Events Other Poker Strategy     High Stakes PL Omaha     Small Stakes PL Omaha     Omaha/8     Stud     Draw and Other Poker Live Poker     Casino & Cardroom Poker         Venues & Communities         Regional Communities     Venues & Communities     Tournament Events         WPT.com     Home Poker     Cash Strategy     Tournament Strategy Internet Poker     Internet Poker         nj.partypoker.com         Global Poker         MPN – Microgaming Poker Network         Big Ugly Poker     Commercial Software     Software         Commercial Software         Free Software General Gambling     Backgammon Forum hosted by Bill Robertie.     Probability     Sports Betting     Other Gambling Games 2+2 Communities     Other Other Topics         OOTV         Game of Thrones     The Lounge: Discussion+Review     EDF     Las Vegas Lifestyle     BBV4Life         omg omg omg     House of Blogs Sports and Games     Sporting Events         Single-Team Season Threads         Fantasy Sports     Fantasy Sports, sponsored by Draftboard.com         Sporting Events     Wrestling     Golf     Chess and Other Board Games     Video Games         League of Legends         Hearthstone     Puzzles and Other Games Other Topics     Politics     History     Business, Finance, and Investing     Science, Math, and Philosophy     Religion, God, and Theology     Travel     Health and Fitness     Laughs or Links!     Computer Technical Help     Programming International Forums     Deutsch         BBV [German]     Français     Two Plus Two en Español

All times are GMT -4. The time now is 09:57 AM.

 Contact Us - Two Plus Two Publishing LLC - Privacy Statement - Top