Saving a large array for faster access

I have a 5 dimensional array where all signs range from 2-14. It contains all the possible permutations of a sequence of 5 numbers. This array contains 525,720 permutations, which takes quite a lot of time to calculate. (5-7 seconds on my Macbook pro). It should be used as a lookup table in order to access the value in constant time or, more specifically, the value of a particular poker hand:

array[2][3][4][5][7] // 1 array[5][5][5][5][14] // 2000 

Is there a faster way to create this array? I thought about saving the array in some way, and then loading it every time my program starts, but are there any effective ways to do this?

I am not very familiar with perseverance. I really don't know if it was worth it for me to load it from disk, rather than create it every time. I know about Hibernate, but does it look like a kink, just to keep a single array?

+4
source share
7 answers

What you probably want to do if computing an array is too expensive is serializing it. This basically puts a binary copy of the data on a storage medium (for example, on your hard drive), which you can load very quickly.

Serialization is pretty simple. Here's a tutorial that is specifically designed for serializing arrays.

Since these values ​​are likely to change only if your poker hand rating algorithm changes, it should be fine to just send a serialized file. The file size should be reasonable if the data stored in each element of the array is not too large (if, for example, it is a 16-bit integer, the file size will be about 1 MB).

+1
source

Write it through a MappedByteBuffer. Create a large enough file, draw it, get asIntBuffer (), enter your numbers.

Then you can match it later and access it through IntBuffer.get (obvious math indices).

This greatly speeds up serialization.

+2
source

I would start by expanding your dimensions for indexing:

provided that you have a set of indices (from your first example, valid values ​​are from 2 to 14):

  i1 = 2 i2 = 3 i3 = 5 i4 = 6 i5 = 7 

and created your array using

  short array[] = new short[13 * 13 * 13 * 13 * 13]; ... 

then access to each element becomes

  array[(i1 - 2) * 13 * 13 * 13 * 13 + (i2 - 2) * 13 * 13 * 13 + (i3 - 2) * 13 * 13 + (i4 - 2) * 13 + (i5 - 2)] 

This array will consume much less memory, since you do not need to create an additional layer of objects for each dimension, and you can easily save all the contents in a file and load it into one list.

It will also move faster around this array, because you will do 1/5 of the array search.

Also, pulling the number of elements in each dimension will save significant memory.

To clear your code, this array must be hidden inside the object using the get and set method, which takes five indexes.

+2
source

Not a direct answer to your original question, but ...

If you're trying to make quick poker scores, you need to make sure you read The Great Poker Hand Evaluator Roundup .

In particular: Cactus Kev Poker Hand Appraiser .

I was involved in a lengthy discussion about conducting the fastest poker scores in 5th and 7th hand games, where most of this material comes from. Honestly, I don’t see how these estimates will be executed faster until you can keep all manual values ​​of C (52.5) ​​or 2,598,960 in the look-up table.

+2
source

I'm not sure your poker permutations are correct, but anyway ...

You can make the initialization of your array about 120 times faster , saving every permutation of a given poker hand right away. This works because the "value" of a poker hand does not depend on the order of the cards.

First calculate the value for the hand. Let's say you have five cards (c1, c2, c3, c4, c5):

 handValue = EvaluateHand(c1, c2, c3, c4, c5); // Store the pre-calculated hand value in a table for faster lookup hand[c1][c2][c3][c4][c5] = handValue; 

Then assign handValue to all permutations of that hand (i.e. the order of the cards will not change handValue).

 hand[c1][c2][c3][c5][c4] = handValue; hand[c1][c2][c4][c3][c5] = handValue; hand[c1][c2][c4][c5][c3] = handValue; hand[c1][c2][c5][c3][c4] = handValue; hand[c1][c2][c5][c4][c3] = handValue; : etc. : hand[c5][c4][c3][c2][c1] = handValue; 
+1
source

Few things:

If it's for poker hands, you can't just save 2-14. You also need to save the costume. This really means you need to store 0-51. Otherwise, you have no way of knowing whether array[2][3][4][5][6] direct or direct flash.

If you really don't need to store costumes for your application, and you really want to do it in an array, use indexes 0-12, not 2-14. This will allow you to use an array of 13 Γ— 13 Γ— 13 Γ— 13 Γ— 13 (371,293 elements) instead of an array of 15 Γ— 15 Γ— 15 Γ— 15 Γ— 15 (759 375 elements). Whenever you access an array, you just need to subtract 2 from each index. (I'm not sure where you got your 525 720 score ...)

0
source

First of all, thanks for your enthusiasm!

So the direct approach seems to just serialize it. I think I will try this first to check the performance and see if that is enough. (I think so).

About MappedByteBuffer ... Is it right to understand that this allows you to load part of a serialized array? So, am I loading the values ​​that I need at runtime, instead of loading the whole array at startup?

@Jennie Claims are stored in another array. I'm not sure if this is the best way to go, because there are many things to consider on this particular issue. A flash is basically a card with a high card, with a different value ... So, there is no real reason to keep the same permutations (high cards) twice, but now this is the way to do it. I think the path is a hash function, so I can easily convert the high map values ​​to flush values, but I have not given many such thoughts.

On signs, you are, of course, right. This is for the moment. It’s easier for me to check the value of β€œ2 3 4 5 6” by simply pasting the map values ​​now ... Later I cut out the array!

0
source

Source: https://habr.com/ru/post/1300335/


All Articles