예제 #1
0
 /**
  * Index a hand on every round. This is not more expensive than just indexing the last round.
  *
  * @param cards
  * @param indices an array where the indices for every round will be saved to
  * @return hands index on the last round
  */
 public long indexAll(int[] cards, long[] indices)
 {
     if (rounds > 0)
     {
         HandIndexerState state = new HandIndexerState();
         for (int i = 0; i < rounds; i++)
         {
             indices[i] = indexNextRound(state, cards);
         }
         return(indices[rounds - 1]);
     }
     return(0);
 }
예제 #2
0
        /**
         * Incrementally index the next round.
         *
         * @param state
         * @param cards the cards for the next round only!
         * @return hand's index on the latest round
         */
        public long indexNextRound(HandIndexerState state, int[] cards)
        {
            int round = state.round++;

            int[] ranks        = new int[SUITS];
            int[] shiftedRanks = new int[SUITS];

            for (int i = 0, j = roundStart[round]; i < cardsPerRound[round]; ++i, ++j)
            {
                int rank = cards[j] >> 2, suit = cards[j] & 3, rankBit = 1 << rank;
                ranks[suit]        |= rankBit;
                shiftedRanks[suit] |= (rankBit >> BitOperations.PopCount((uint)((rankBit - 1) & state.usedRanks[suit])));
            }

            for (int i = 0; i < SUITS; ++i)
            {
                int usedSize = BitOperations.PopCount((uint)state.usedRanks[i]), thisSize = BitOperations.PopCount((uint)ranks[i]);
                state.suitIndex[i]      += state.suitMultiplier[i] * rankSetToIndex[shiftedRanks[i]];
                state.suitMultiplier[i] *= nCrRanks[RANKS - usedSize, thisSize];
                state.usedRanks[i]      |= ranks[i];
            }

            for (int i = 0, remaining = cardsPerRound[round]; i < SUITS - 1; ++i)
            {
                int thisSize = BitOperations.PopCount((uint)(ranks[i]));
                state.permutationIndex      += state.permutationMultiplier * thisSize;
                state.permutationMultiplier *= remaining + 1;
                remaining -= thisSize;
            }

            int  configuration = permutationToConfiguration[round][state.permutationIndex];
            int  piIndex       = permutationToPi[round][state.permutationIndex];
            int  equalIndex    = configurationToEqual[round][configuration];
            long offset        = configurationToOffset[round][configuration];

            int[] pi = suitPermutations[piIndex];

            int[] suitIndex = new int[SUITS], suitMultiplier = new int[SUITS];
            for (int i = 0; i < SUITS; ++i)
            {
                suitIndex[i]      = state.suitIndex[pi[i]];
                suitMultiplier[i] = state.suitMultiplier[pi[i]];
            }
            long index = offset, multiplier = 1;

            for (int i = 0; i < SUITS;)
            {
                long part, size;

                if (i + 1 < SUITS && equal[equalIndex, i + 1])
                {
                    if (i + 2 < SUITS && equal[equalIndex, i + 2])
                    {
                        if (i + 3 < SUITS && equal[equalIndex, i + 3])
                        {
                            Swap(suitIndex, i, i + 1);
                            Swap(suitIndex, i + 2, i + 3);
                            Swap(suitIndex, i, i + 2);
                            Swap(suitIndex, i + 1, i + 3);
                            Swap(suitIndex, i + 1, i + 2);
                            part = suitIndex[i]
                                   + nCrGroups[suitIndex[i + 1] + 1, 2]
                                   + nCrGroups[suitIndex[i + 2] + 2, 3]
                                   + nCrGroups[suitIndex[i + 3] + 3, 4];
                            size = nCrGroups[suitMultiplier[i] + 3, 4];
                            i   += 4;
                        }
                        else
                        {
                            Swap(suitIndex, i, i + 1);
                            Swap(suitIndex, i, i + 2);
                            Swap(suitIndex, i + 1, i + 2);
                            part = suitIndex[i] + nCrGroups[suitIndex[i + 1] + 1, 2]
                                   + nCrGroups[suitIndex[i + 2] + 2, 3];
                            size = nCrGroups[suitMultiplier[i] + 2, 3];
                            i   += 3;
                        }
                    }
                    else
                    {
                        Swap(suitIndex, i, i + 1);
                        part = suitIndex[i] + nCrGroups[suitIndex[i + 1] + 1, 2];
                        size = nCrGroups[suitMultiplier[i] + 1, 2];
                        i   += 2;
                    }
                }
                else
                {
                    part = suitIndex[i];
                    size = suitMultiplier[i];
                    i   += 1;
                }

                index      += multiplier * part;
                multiplier *= size;
            }
            return(index);
        }