Представляйте покерну руку на 5 картках


11

Колода карт - 52. Рука - 5 карт із 52 (не може мати копію).

Яка найменша кількість бітів, щоб представити руку з 5 карт і як?
Рука НЕ ​​залежить від порядку (KQ = QK). 64329 = 96432

Так, можна використовувати 52 біт. Це може представляти руку будь-якої кількості карт.

Дано руці рівно 5 карт є спосіб представити її менше ніж 52 бітами.

Одну карту можна представити 6 бітами = 64. Тож просто можна використовувати 6 біт * 5 карт = 30 біт. Але це залежатиме від порядку. Я міг би просто сортувати, і це має працювати. Якщо це не спрацює, будь ласка, дайте мені знати.

Чи є спосіб отримати ключ до 32 біт або нижче, і не доведеться сортувати кортеж 5 карт.

Це для моделювання покеру, і сортування було б значно накладніше, ніж просто генерування рук. Якщо у мене є словник з відносним значенням кожної руки, це два прості пошуки та порівняння для порівняння значення двох рук. Якщо мені доведеться спочатку сортувати руки, які є великими порівняно з двома пошуками та порівнянням. У симуляції порівняють мільйони. Я не буду відбирати руки від моделювання. Цей сорт не простий, як 52 51 50 49 48 перед 52 51 50 49 47. У вас можуть бути прямолінійні квадрати.

Є 2598960 можливих 5 карт карт. Це кількість рядків. Ключ - 5 карт. Я хотів би отримати ключ, який має 32 біти або під тим, де картки не потрібно сортувати спочатку.

Не можна просто замовити список, скільки зав’язують руки. Костюм - це лопата, клуб, діамант та серце. 7c 8c 2d 3d 4s = 7s 8s 2c 3c 4h. Існує велика кількість зв’язків.

Наступний крок - 64 біти і скористається хітом сорту, а не подвійним розміром ключа.

Я перевірив і SortedSet<int> quickSort = new SortedSet<int>() { i, j, k, m, n };подвоїв час операції, але все ще можу це зробити.

Він стає складнішим. Мені потрібно вміти представляти човен як двійки старше п’яти (22255). Тож сортування їх порушує це. Я знаю, що ти скажеш, але це швидко. Так, це швидко і банально, але мені потрібно якомога швидше.

C # для прийнятої відповіді:

private int[] DeckXOR = new int[] {0x00000001,0x00000002,0x00000004,0x00000008,0x00000010,0x00000020,0x00000040,
                                    0x00000080,0x00000100,0x00000200,0x00000400,0x00000800,0x00001000,0x00002000,
                                    0x00004000,0x00008000,0x00010000,0x00020000,0x00040000,0x00080000,0x00100000,
                                    0x00200000,0x00400000,0x00800000,0x01000000,0x02000000,0x04000000,0x07fe0000,
                                    0x07c1f000,0x0639cc00,0x01b5aa00,0x056b5600,0x04ed6900,0x039ad500,0x0717c280,
                                    0x049b9240,0x00dd0cc0,0x06c823c0,0x07a3ef20,0x002a72e0,0x01191f10,0x02c55870,
                                    0x007bbe88,0x05f1b668,0x07a23418,0x0569d998,0x032ade38,0x03cde534,0x060c076a,
                                    0x04878b06,0x069b3c05,0x054089a3};
public void PokerProB()
{
    Stopwatch sw = new Stopwatch();
    sw.Start();
    HashSet<int> cardsXOR = new HashSet<int>();
    int cardXOR;
    int counter = 0;
    for (int i = 51; i >= 4; i--)
    {
        for (int j = i - 1; j >= 3; j--)
        {
            for (int k = j - 1; k >= 2; k--)
            {
                for (int m = k - 1; m >= 1; m--)
                {
                    for (int n = m - 1; n >= 0; n--)
                    {
                        counter++;
                        cardXOR = DeckXOR[i] ^ DeckXOR[j] ^ DeckXOR[k] ^ DeckXOR[m] ^ DeckXOR[n];
                        if (!cardsXOR.Add(cardXOR))
                            Debug.WriteLine("problem");
                    }
                }
            }
        }
    }
    sw.Stop();
    Debug.WriteLine("Count {0} millisec {1} ", counter.ToString("N0"), sw.ElapsedMilliseconds.ToString("N0"));
    Debug.WriteLine("");
}

4
Використовуйте кодований вручну алгоритм сортування, який працює для сортування списків довжиною 5. Це, мабуть, швидше, ніж функція бібліотеки, яку ви зараз використовуєте.
Yuval Filmus

1
Я не розумію, чому ви говорите "Сорт не простий" . Родом є простим - перетворити кожну карту в число від 1 до 52, так що рука представлена у вигляді списку (довжиною 5) карт. Сортувати цей список. Це лише проблема сортування списку з 5 цілих чисел, що можна зробити дуже швидко, як зазначає Юваль. Я пропоную вам виміряти, перш ніж вважати, що це занадто повільно, але я гадаю, що сортування такого списку буде дуже швидким і навіть може бути швидшим, ніж зчитування пам'яті з випадковим доступом, яке не потрапляє в кеш.
DW

@dw Так, сорт простий, але те, що я роблю (мільйони разів), є простим. Я тестував і сорт подвоює час.
папараццо

1
@Paparazzi Ні, Yuval пропонує вам написати свій власний розпорядок сортування, який спеціально налаштований на сортування п’яти чисел між 1 і 52. Ви спробували скористатися бібліотечною програмою, яка повільна, оскільки вона набагато загальніша за це і тому, що рекурсивна природа Квіксорт робить його неефективним у списках.
Девід Річербі

На практиці більшість елементів, які не <16 біт, також можуть бути 32 біти. Отже, оскільки вам потрібно щонайменше 23 біта, будь-яке кодування, яке використовує <= 32 біта, ймовірно, є життєздатним. Тривіальні 6 біт на одну карту * 5 кодування карти працює досить добре. Є одне застереження: 23-бітний індекс масиву набагато кращий, ніж індекс масиву 32 біт.
MSalters

Відповіді:


10

С[52,25,11]С27×521152А1,,А52Аi271100а,б,c,г,еАаАбАcАгАеН1,Н210-2|Н1Н2|10

Боб Дженкінс описує такий код на своєму сайті , і з цього ми можемо витягти масив

0x00000001,0x00000002,0x00000004,0x00000008,0x00000010,0x00000020,0x00000040,
0x00000080,0x00000100,0x00000200,0x00000400,0x00000800,0x00001000,0x00002000,
0x00004000,0x00008000,0x00010000,0x00020000,0x00040000,0x00080000,0x00100000,
0x00200000,0x00400000,0x00800000,0x01000000,0x02000000,0x04000000,0x07fe0000,
0x07c1f000,0x0639cc00,0x01b5aa00,0x056b5600,0x04ed6900,0x039ad500,0x0717c280,
0x049b9240,0x00dd0cc0,0x06c823c0,0x07a3ef20,0x002a72e0,0x01191f10,0x02c55870,
0x007bbe88,0x05f1b668,0x07a23418,0x0569d998,0x032ade38,0x03cde534,0x060c076a,
0x04878b06,0x069b3c05,0x054089a3

252-27-1=225-1


Я точно не слідую. Скільки бітів для цього потрібно для руки?
папараццо

Для цього потрібно 27 біт. Ви можете використовувати будь-яку більшу кількість біт.
Yuval Filmus

Дякую. Я перевірив, і цифри є унікальними і <= 32 біт. Чи можу я вивести 5 карт із числа? Якщо не добре, просто запитую.
папараццо

Так, це проста лінійна алгебра. Ви можете використовувати правильну матрицю, щоб повернути вектор довжиною 52 з 5 одиницями. Я дам вам зрозуміти це.
Yuval Filmus

13

нlgнlg2598960=22

Як працює представництво? Існують різні варіанти з різними компромісами. Я перелічую два нижче.

Словник із жорстким кодом

У цьому випадку кількість можливих 5-карткових карт є достатньо малою, щоб ви могли просто скласти жорстко закодований словник, який перелічує всі 2598960 рук, і ви представляєте руку за її індексом у словнику (представлений у двійковій).

Іншими словами, словник може бути відсортованим списком рук. Кожна рука - це 5-картка карт у руці, у відсортованому порядку. Ви можете шукати руку в словнику за допомогою двійкового пошуку та знаходити його відповідний індекс; і задавши індекс, ви можете знайти відповідну руку. Або ви можете зберігати словник у вигляді хешмапу, який відображається від руки до його індексу. Індекс є цілим числом від 0 до 2598959, тому його можна представити, використовуючи 23 біти.

Цей підхід буде працювати і дуже простий у програмі, але він марнотратний у просторі (розмір програми, що виконується).

Ранжування / відключення

Як варіант, якщо вам байдуже, є кращі методи. Дивіться, наприклад, будь-яку з наступних посилань:

Загальна тема відома як "ранжування (і незв’язну) комбінацій". Вони є трохи складнішими для реалізації та розуміння, але уникайте необхідності включати в програму сложно кодований словник.


Я оновлю питання. Так, є 2598960 рук. У словнику буде стільки рядків. Моя проблема - генерація ключа. З 5 карт мені потрібно створити ключ для пошуку словника.
папараццо

@ Paparazzi, якщо ви використовуєте словниковий підхід, рука є ключовою. Іншими словами, ключ - це 5-картка карт в руці (у відсортованому порядку). Словник можна зберігати як хештеб, використовуючи його як ключ. Якщо вам не подобаються витрати на пам'ять словника, використовуйте альтернативний підхід: ранжирування / відключення.
DW

Так, я знаю, що можу отримати ключ з 30 біт, якщо сортую. Мені цікаво, чи є спосіб отримати ключ 32 біта або нижче, не сортуючи 5 карт карт. Я буду дивитись на ранги та рейтинги.
папараццо

Я не слідкую за рейтингом / відмовою, але дякую. Я спробую це зрозуміти. Також є можливості зв’язків. Зв’язок дуже багато.
папараццо


3

Ви можете сортувати п’ять елементів і одночасно перевірити наявність дублікатів без порівнянь на деяких процесорах: Припустимо, процесор має швидку інструкцію, яка визначає позицію найвищого набору бітів, і швидку інструкцію обчислення числа лише з n-го бітного набору .

Нехай біт (n) - число з точно встановленим n-м бітом. Нехай найвищий_біт (х) - це число найвищого біта, встановленого в число х, з невизначеним значенням, якщо х = 0. Нехай x ^ y - ексклюзив - або з x і y.

Дано п'ять чисел a, b, c, d і e, кожне від 0 до 51, що представляють п’ять карток у руці.

Нехай x = біт (а) ^ біт (б) ^ біт (в) ^ біт (г) ^ біт (е).

Нехай A = найвищий_біт (x), змінить x на x ^ біт (A).

Нехай B = найвищий_біт (x), змінить x на x ^ біт (B).

Нехай C = найвищий_біт (x), змінить x на x ^ біт (C).

Нехай D = найвищий_біт (x), змінить x на x ^ біт (D).

Нехай E = найвищий_біт (x).

Якщо x = 0, то у нумерах a, b, c, d та e були дублікати. В іншому випадку використовуйте A * біт (24) + B * біт (18) + C * біт (12) + D * біт (6) + E в якості кодування руки, де A, B, C, D і E визначено як вище. Це кодує руку як 30-бітну рядок, при цьому сортування проводиться дуже ефективно.


Для цього використовується 52 біти?
папараццо

@Paparazzi, ні. Погляньте ще раз на останній абзац. Я відредагував це, щоб спробувати надати ще більшу чіткість.
DW

1
Для цього потрібен 64-розрядний процесор, але кінцевий результат - лише 30 біт.
Yuval Filmus
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.