there would be any speed advantages for simulations?
But I am not sure I understand where you get a connection with speed here ... And what do you compare with what when you are talking about "advantages".
Quote: PaigowdanYes, bit mapping as a data structure affords great speed in processing, but may make for messy programming.
The only thing that makes for messy programming is messy programmers.
Bit mapping isn't really a data structure. But if you design a data structure that uses a bit map, that is likely to make your program work slower (or, perhaps, as fast), not faster, but require less memory (unless you are trying to map like every poker hand to a bit or something like that - that would be both slow, and bloated).
I was an old school ALGOL programmer on Burroughs (Unisys) equipment back in the day, and by using DEFINEs properly, bit mapping can indeed be well-organized.
Quote: teliotThis site has helped me a lot along the way: Poker hand evaluator roundup
Thanks for the responses, and in particular the above site. I'm afraid I saw too much of myself in the paragraph on "naive simulators" and so will
have to rethink a few things.
My original plan was to code in pascal; will using the provided code be possible in that language, or will I have to learn C++ (and get a compiler for that too)?
To start, I recommend using pre-populated arrays for the combin(n,k) function with a value of 0 for evaluations that would normally result in an error condition, such as combin(2, 3). Here would be the code for a 52-card deck:
int[] Choose2 = { 0, 0, 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 66, 78, 91, 105, 120, 136, 153, 171, 190, 210, 231, 253, 276, 300,
325, 351, 378, 406, 435, 465, 496, 528, 561, 595, 630, 666, 703, 741, 780, 820, 861, 903, 946, 990, 1035, 1081, 1128, 1176, 1225,
1275, 1326 };
int[] Choose3 = { 0, 0, 0, 1, 4, 10, 20, 35, 56, 84, 120, 165, 220, 286, 364, 455, 560, 680, 816, 969, 1140, 1330, 1540, 1771,
2024, 2300, 2600, 2925, 3276, 3654, 4060, 4495, 4960, 5456, 5984, 6545, 7140, 7770, 8436, 9139, 9880, 10660, 11480, 12341, 13244,
14190, 15180, 16215, 17296, 18424, 19600, 20825, 22100 };
int[] Choose4 = { 0, 0, 0, 0, 1, 5, 15, 35, 70, 126, 210, 330, 495, 715, 1001, 1365, 1820, 2380, 3060, 3876, 4845, 5985, 7315,
8855, 10626, 12650, 14950, 17550, 20475, 23751, 27405, 31465, 35960, 40920, 46376, 52360, 58905, 66045, 73815, 82251, 91390,
101270, 111930, 123410, 135751, 148995, 163185, 178365, 194580, 211876, 230300, 249900, 270725 };
int[] Choose5 = { 0, 0, 0, 0, 0, 1, 6, 21, 56, 126, 252, 462, 792, 1287, 2002, 3003, 4368, 6188, 8568, 11628, 15504, 20349, 26334,
33649, 42504, 53130, 65780, 80730, 98280, 118755, 142506, 169911, 201376, 237336, 278256, 324632, 376992, 435897, 501942, 575757,
658008, 749398, 850668, 962598, 1086008, 1221759, 1370754, 1533939, 1712304, 1906884, 2118760, 2349060, 2598960 };
int[] Choose6 = { 0, 0, 0, 0, 0, 0, 1, 7, 28, 84, 210, 462, 924, 1716, 3003, 5005, 8008, 12376, 18564, 27132, 38760, 54264, 74613,
100947, 134596, 177100, 230230, 296010, 376740, 475020, 593775, 736281, 906192, 1107568, 1344904, 1623160, 1947792, 2324784,
2760681, 3262623, 3838380, 4496388, 5245786, 6096454, 7059052, 8145060, 9366819, 10737573, 12271512, 13983816, 15890700, 18009460,
20358520 };
int[] Choose7 = { 0, 0, 0, 0, 0, 0, 0, 1, 8, 36, 120, 330, 792, 1716, 3432, 6435, 11440, 19448, 31824, 50388, 77520, 116280,
170544, 245157, 346104, 480700, 657800, 888030, 1184040, 1560780, 2035800, 2629575, 3365856, 4272048, 5379616, 6724520, 8347680,
10295472, 12620256, 15380937, 18643560, 22481940, 26978328, 32224114, 38320568, 45379620, 53524680, 62891499, 73629072, 85900584,
99884400, 115775100, 133784560 };
Then if you number each card from 0 to 51, and each hand from 0 to 133784559, you can convert 7 card indexes to a hand index as follows:
Choose7[card7] + Choose6[card6] + Choose5[card5] + Choose4[card4] + Choose3[card3] + Choose2[card2] + card1
...where card7 is the highest-numbered card index and card1 is the lowest-numbered card index (it is critical that the card indexes are sorted from highest to lowest).
Then, to convert a hand index (0 ... 133784559) to card indexes, use the following logic:
int card1 = hand_index, card2, card3, card4, card5, card6, card7;
card7 = 51; while (Choose7[card7] > card1) { card7--; } card1 -= Choose7[card7];
card6 = card7 - 1; while (Choose6[card6] > card1) { card6--; } card1 -= Choose6[card6];
card5 = card6 - 1; while (Choose5[card5] > card1) { card5--; } card1 -= Choose5[card5];
card4 = card5 - 1; while (Choose4[card4] > card1) { card4--; } card1 -= Choose4[card4];
card3 = card4 - 1; while (Choose3[card3] > card1) { card3--; } card1 -= Choose3[card3];
card2 = card3 - 1; while (Choose2[card2] > card1) { card2--; } card1 -= Choose2[card2];
...where hand_index is the hand index from 0 to 133784559. The result will be 7 card indexes in sorted order (card1 being the lowest-numbered card index, and card7 the highest-numbered one), just as was required for the function to compute the hand index.
Hope that helps!
Quote: JBThen if you number each card from 0 to 51, and each hand from 0 to 133784559, you can convert 7 card indexes to a hand index as follows:
Choose7[card7] + Choose6[card6] + Choose5[card5] + Choose4[card4] + Choose3[card3] + Choose2[card2] + card1
...where card7 is the highest-numbered card index and card1 is the lowest-numbered card index (it is critical that the card indexes are sorted from highest to lowest).
Then, to convert a hand index (0 ... 133784559) to card indexes, use the following logic:int card1 = hand_index, card2, card3, card4, card5, card6, card7;
card7 = 51; while (Choose7[card7] > card1) { card7--; } card1 -= Choose7[card7];
card6 = card7 - 1; while (Choose6[card6] > card1) { card6--; } card1 -= Choose6[card6];
card5 = card6 - 1; while (Choose5[card5] > card1) { card5--; } card1 -= Choose5[card5];
card4 = card5 - 1; while (Choose4[card4] > card1) { card4--; } card1 -= Choose4[card4];
card3 = card4 - 1; while (Choose3[card3] > card1) { card3--; } card1 -= Choose3[card3];
card2 = card3 - 1; while (Choose2[card2] > card1) { card2--; } card1 -= Choose2[card2];
...where hand_index is the hand index from 0 to 133784559. The result will be 7 card indexes in sorted order (card1 being the lowest-numbered card index, and card7 the highest-numbered one), just as was required for the function to compute the hand index.
Hope that helps!
These concepts are gold; they are invaluable to making a poker analyzer.
The Wizard has some of the same info at the bottom of this page, but his requires numbers sorted low to high, and is not quite as straight forward:
Video Poker Programming Tips
Quote: weaselmanWhy bother? Save 4 bytes per hand? How many hands do you need to have in memory at the same time?
It depends on the application. For example, if you're writing something in Java then this would be the way to go since Java's memory constraints are restrictive. If you're creating a binary data file then you definitely want to go this route to minimize the disk space used for it.
Another reason is to standardize the sequence of the cards (that is, to store combinations and not permutations). It would obviously be quicker to use a 64-bit number and just bit-shift the card indexes if memory is not an issue but speed is, but even if you do that you'll still have to sort the card indexes.
Quote: JBIt depends on the application. For example, if you're writing something in Java then this would be the way to go since Java's memory constraints are restrictive.
Not sure what you mean by this. Java long is 8 bytes just like in (64 bit) C.
Quote:If you're creating a binary data file then you definitely want to go this route to minimize the disk space used for it.
Nah... Gzip will pack it better than you ever would anyway.
Quote:Another reason is to standardize the sequence of the cards (that is, to store combinations and not permutations). It would obviously be quicker to use a 64-bit number and just bit-shift the card indexes if memory is not an issue but speed is, but even if you do that you'll still have to sort the card indexes.
I don't understand what this means. Sort the indexes? Why?
Quote: weaselmanNot sure what you mean by this. Java long is 8 bytes just like in (64 bit) C.
Yes but the default amount of memory you can use for arrays is pretty limited, when designing an applet for the web anyway.
Quote: weaselmanNah... Gzip will pack it better than you ever would anyway.
If adding another layer of complexity and slowing things down is worth it, sure.
Quote: weaselmanI don't understand what this means. Sort the indexes? Why?
For a 7-card hand, there are 7! = 5040 ways to arrange the card indexes. You don't want to store each unique hand 5040 times in an array with 674274182400 subscripts (consuming about 4.9 terabytes); it would be better to sort the card indexes and store each hand once in an array with 133784560 subscripts. Even so, that's about 1GB of memory if you use 64-bit integers, and of course only half of that if you use 32-bit integers.
Quote: JBYes but the default amount of memory you can use for arrays is pretty limited, when designing an applet for the web anyway.
How much is it? I have not done applets for quite a while, don't remember anymore... Who uses defaults nowadays anyway?
Quote:If adding another layer of complexity and slowing things down is worth it, sure.
Piping data through gzip is hardly "complexity". Especially, was compared.to your mapping algorithm :-) As for speed, reading and writing gzipped files is generally faster, than unpacked ones. Even if there is no significant reduction in size, it does not take any longer because io is done in parallel with gzip CPU activity.
Quote:For a 7-card hand, there are 7! = 5040 ways to arrange the card indexes. You don't want to store each unique hand 5040 times
Ah, yeah, that makes sense. Though, I am still not sure what kind of application requires storing this many hands.
If you are doing a simulator, and just want to log every hand, you'd have to store as many hands as you play anyway, regardless of how they are represented.
Quote: weaselmanHow much is it? I have not done applets for quite a while, don't remember anymore... Who uses defaults nowadays anyway?
I don't know what the specific limit is, but I ran into problems trying to create an applet that generates video poker strategies. I would assume that those who don't specifically tinker with Java's memory settings are the ones who use defaults.
Quote: weaselmanPiping data through gzip is hardly "complexity". Especially, was compared.to your mapping algorithm :-) As for speed, reading and writing gzipped files is generally faster, than unpacked ones. Even if there is no significant reduction in size, it does not take any longer because io is done in parallel with gzip CPU activity.
We may be arguing two different things here. I see my method to map hands as the most efficient and simple method possible. Using compression only comes into play if you're saving or loading the array to/from a file (or memory stream).
Quote: weaselmanAh, yeah, that makes sense. Though, I am still not sure what kind of application requires storing this many hands.
If you are doing a simulator, and just want to log every hand, you'd have to store as many hands as you play anyway, regardless of how they are represented.
For a calculator it would be useful. For example, if you know two hole cards, loop through the other 5 cards, calculate the combination, and look up the hand type in the array; this is much faster than calling a separate function to determine the hand rank due to the overhead of calling a function 2,118,760 times.