I think that consecutive values are "folded together". Where possible, I imagine that results which lead to the same poker result structure hit the same index regardless of the individual card values. So it's more compact than a strict representation of combinations.
That said, it's definitely not a byte array. Consider, for example, that 8730 is an "ending value" in this array and that most of the values in the array are indices back into the array. For example: >./HR 32487781 Also, if you want to think of this as a "hash" you have to think of it as a "perfect hash" - in other words, at no point do you have conflicting results "hashed" the same way. That said, looking at the numbers, this packing method has indeed yielded a "compression factor" of about 4: 7!52 133784560 #HR 32487834 (7!52) %#HR 4.11799 Thanks, -- Raul On Sun, Jan 3, 2016 at 11:12 AM, 'Pascal Jasmin' via Programming <[email protected]> wrote: > assuming this is the correct result, > > (HR {~ +)/@:(,&53) 1 5 9 12 20 25 42 > > 8730 > > it is first looking up the 42+53 index in HR, then looking up 25 + that > index... an interesting way to hash. > > > Some optimizations of HR would include making it 0 based. There is probably > a +/@:+/\ or */ version of the hash > > but I don't understand HR > > 52!~5 > 2598960 > > with 7 cards would make 21 queries on this list, which seems like it would be > slower, but there may be a quicker formula to obtain the index into this list > (similar to A.) > > > HR is probably, > > 52!~7 > 133784560 > > > with 1 byte per index (represents pair, 4ofakind etc), and so storing it as > char instead of int would use much less memory, and improve cache use even if > your machine has tons of memory. > > An easy way to make HR would be through symbols (s:) where the naming > alphabet can come from a-zA-Z (52 yay!). It would let you make 1 fast lookup > per hand, constructing the symbol from indexing into alphabet. > > ----- Original Message ----- > From: Raul Miller <[email protected]> > To: Programming forum <[email protected]> > Sent: Sunday, January 3, 2016 10:26 AM > Subject: Re: [Jprogramming] Faster array lookup? (poker hand evaluator) > > If anyone want to play with this, they should have a copy of the HR file: > > https://github.com/christophschmalhofer/poker/blob/master/XPokerEval/XPokerEval.TwoPlusTwo/HandRanks.dat > > Or you can download the entire repository from github. > > You can use the "View Raw" link to download a copy. > > I was hoping you could use map_jmf_ to load a copy of the file, but > unfortunately that's currently broken for 64 bit j804 (or at least for > the j804 version I'm currently running. > > F=: > '/Users/rauldmiller/src/poker-master/XPokerEval/XPokerEval.TwoPlusTwo/HandRanks.dat' > load'jmf' > JINT map_jmf_ 'HR';F > #HR > 16243917 > > That should be 3590398 > > So although JINT is 4 (4 bytes per integer) my J implementation is > acting like it's 8 bytes per integer. > > So, let's do this the other way. If you are copying my footsteps, > you'll want to cleanup first: > > erase 'HR' > 1 > unmapall_jmf_'' > 0 > > Then: > HR=: _2 ic fread F > #HR > 32487834 > #~.HR > 620299 > > (HR {~ +)/@:(,&53) 1 5 9 12 20 25 42 > 8730 > > In contrast: > (HR {~ +/)@:(,&53) 1 5 9 12 20 25 42 > 5830 > > By the way, if you want a slightly deeper dive into the result we're > generating here: > > handtypes=:<;._2]0 :0 > > high card > pair > 2 pairs > 3 of a kind > straight > flush > full house > 4 of a kind > straight flush > ) > > handtypes {::~ <.4096 %~ (HR {~ +)/@:(,&53) 1 5 9 12 20 25 42 > pair > > Anyways... > > My impression is that this algorithm is a carefully designed highly > sequential algorithm. J runs those slowly. If you want performance, I > think you should use J's > http://www.jsoftware.com/help/user/call_procedure.htm mechanism to run > that routine (compile a cover function designed for pulling the > argument data from a J array and exporting the result to a J array and > compile that with a C api). This would give you the performance of > the scalar algorithm and the convenience of J's interactive > environment. Of course, there's a bit of work in setting that up in > the first place, but honestly some work is unavoidable for anything > worth doing. > > But maybe my initial impression wrong and there's some transformation > of that data set which gives adequate performance in J? I'm not seeing > anything like that, but I've been wrong plenty of times before... > > Anyways... I hope this helps. > > Thanks, > > -- > Raul > > > > On Sun, Jan 3, 2016 at 9:15 AM, 'Pascal Jasmin' via Programming > <[email protected]> wrote: >> (HR {~ +)/@:(,&53) >> >> >> I'm not sure why the sum is a useful index as I don't think its unique, but >> you are repeating for each card. Perhaps this is intended? >> >> >> (HR {~ +/)@:(,&53) >> >> ----- Original Message ----- >> From: Ryan Eckbo <[email protected]> >> To: J-programming forum <[email protected]> >> Sent: Saturday, January 2, 2016 10:56 PM >> Subject: [Jprogramming] Faster array lookup? (poker hand evaluator) >> >> I've implemented the twoplustwo 7 card poker hand evaluator[1] in J but >> it's >> slower than I expected. The evaluator works by accepting an array of 7 >> integers between 1 and 52, representing a 7 card hand, and uses them as >> indices >> in a lookup table, which returns the best 5 card hand's rank value. >> Here's the >> C code that does this (HR is the lookup table): >> >> int LookupHand(int* pCards) >> { >> int p = HR[53 + *pCards++]; >> p = HR[p + *pCards++]; >> p = HR[p + *pCards++]; >> p = HR[p + *pCards++]; >> p = HR[p + *pCards++]; >> p = HR[p + *pCards++]; >> return HR[p + *pCards++]; >> } >> >> My J version is: >> >> hr=: (HR {~ +)/@:(,&53) NB. hr 1 5 9 12 20 25 42 >> >> This is one of the fastest evaluators out there, for example a >> javascript version >> can run at 20 million evaluations per second. My J version takes 30 >> seconds >> to evaluate just 10 million hands: >> >> hands=. 53,.~ >: ? 1e7 7 $ 52 NB. 10 million hands, with initial index >> 53 added >> 6!:2 '(HR {~ +)/"1 hands' NB. 32.14 sec on a 2.8GHz Mac >> >> I wonder why it's slow and if there's a way to make it faster? >> >> >> [1] >> https://github.com/christophschmalhofer/poker/blob/master/XPokerEval/XPokerEval.TwoPlusTwo.Test/test.cpp >> ---------------------------------------------------------------------- >> For information about J forums see http://www.jsoftware.com/forums.htm > >> ---------------------------------------------------------------------- >> For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm > ---------------------------------------------------------------------- > For information about J forums see http://www.jsoftware.com/forums.htm ---------------------------------------------------------------------- For information about J forums see http://www.jsoftware.com/forums.htm
