Mewakili tangan poker 5 kartu

11

Setumpuk kartu adalah 52. Tangan adalah 5 kartu dari 52 (tidak dapat memiliki duplikat).

Berapa jumlah bit paling sedikit untuk mewakili kartu 5 tangan dan bagaimana?
Tangan TIDAK tergantung pesanan (KQ = QK). 64329 = 96432

Ya, bisa menggunakan 52 bit. Itu bisa mewakili tangan sejumlah kartu.

Diberi tangan adalah tepat 5 kartu apakah ada cara untuk mewakilinya dengan kurang dari 52 bit.

Satu kartu dapat direpresentasikan dengan 6 bit = 64. Jadi bisa saja menggunakan 6 bit * 5 kartu = 30 bit. Tapi itu tergantung pesanan. Saya bisa menyortir dan ini seharusnya berhasil. Jika itu tidak berhasil tolong beri tahu saya.

Apakah ada cara untuk mendapatkan kunci 32 bit atau di bawah dan tidak perlu mengurutkan tuple 5 kartu.

Ini untuk simulasi poker dan pengurutan akan banyak overhead dibandingkan dengan hanya menghasilkan tangan. Jika saya memiliki kamus dengan nilai relatif masing-masing tangan itu adalah dua pencarian sederhana dan perbandingan untuk membandingkan nilai dua tangan. Jika saya harus mengurutkan tangan pertama yang besar dibandingkan dengan dua pencarian dan perbandingan. Dalam simulasi akan membandingkan jutaan. Saya tidak akan mendapatkan tangan yang disortir dari simulasi. Jenisnya tidak sederhana seperti 52 51 50 49 48 sebelum 52 51 50 49 47. Anda dapat memiliki paha depan flush lurus ....

Ada 2598960 kemungkinan 5 kartu. Itu adalah jumlah baris. Kuncinya adalah 5 kartu. Saya ingin mendapatkan kunci yang 32 bit atau di bawah di mana kartu tidak perlu disortir terlebih dahulu.

Tidak bisa hanya memesan daftar sebanyak dasi tangan. Setelannya adalah sekop, pentungan, berlian, dan hati. 7c 8c 2d 3d 4s = 7s 8s 2c 3c 4h. Ada banyak ikatan.

Langkah selanjutnya adalah 64 bit dan akan menerima pukulan semacam itu daripada menggandakan ukuran kunci.

Saya menguji dan SortedSet<int> quickSort = new SortedSet<int>() { i, j, k, m, n };menggandakan waktu operasi tetapi saya masih bisa melakukannya.

Itu menjadi lebih kompleks. Saya harus bisa mewakili perahu sebagai berpasangan lima (22255). Jadi memilah mereka istirahat itu. Saya tahu Anda akan mengatakan tetapi itu cepat. Ya itu cepat dan sepele tetapi saya perlu secepat mungkin.

C # untuk jawaban yang diterima:

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("");
}
paparazzo
sumber
4
Gunakan algoritma penyortiran kode tangan yang berfungsi untuk menyortir daftar panjang 5. Ini mungkin lebih cepat dari fungsi perpustakaan yang saat ini Anda gunakan.
Yuval Filmus
1
Saya tidak mengerti mengapa Anda mengatakan "Jenisnya tidak sederhana" . Semacam itu adalah sederhana - mengkonversi setiap kartu ke nomor dari 1 sampai 52, sehingga tangan diwakili oleh daftar (panjang 5) kartu. Sortir daftar itu. Itu hanya masalah mengurutkan daftar 5 bilangan bulat, yang dapat dilakukan dengan sangat cepat, seperti yang Yuval sebutkan. Saya menyarankan agar Anda mengukur sebelum mengasumsikan bahwa itu terlalu lambat, tetapi tebakan saya adalah bahwa menyortir daftar seperti itu akan sangat cepat dan bahkan mungkin lebih cepat daripada pembacaan memori akses-acak yang tidak mengenai cache.
DW
@ dw Ya jenisnya sederhana tetapi apa yang saya lakukan (jutaan kali) sederhana. Saya menguji dan semacam menggandakan waktu.
paparazzo
1
@ Paparazzi Tidak, Yuval memberitahu Anda untuk menulis rutinitas penyortiran Anda sendiri yang secara khusus disetel untuk menyortir lima angka antara 1 dan 52. Anda mencoba menggunakan rutin perpustakaan, yang lambat karena jauh lebih umum daripada ini dan karena sifat rekursif Quicksort membuatnya sangat tidak efisien pada daftar pendek.
David Richerby
Dalam praktiknya, sebagian besar item yang bukan <= 16 bit mungkin juga 32 bit. Jadi karena Anda membutuhkan setidaknya 23 bit, setiap enkode yang menggunakan <= 32 bit mungkin layak Enkripsi 6 bit per kartu * 5 kartu yang sepele berfungsi cukup baik. Ada satu peringatan: indeks array 23 bit jauh lebih baik daripada indeks array 32 bit.
MSalters

Jawaban:

10

C[52,25,11]C27×521152A1,,A52Ai271100a,b,c,d,eAaAbAcAdAeH1,H2102|H1H2|10

Bob Jenkins menjelaskan kode semacam itu di situsnya , dan dari situ kita dapat mengekstrak array

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

252271=2251

Yuval Filmus
sumber
Saya tidak benar-benar mengikuti. Berapa banyak bit yang dibutuhkan oleh tangan ini?
paparazzo
Perlu 27 bit. Anda dapat menggunakan jumlah bit yang lebih besar.
Yuval Filmus
Terima kasih. Saya menguji dan jumlahnya unik dan <= 32 bit. Bisakah saya mendapatkan 5 kartu dari nomor tersebut? Kalau tidak apa-apa hanya bertanya.
paparazzo
Ya, itu adalah aljabar linier sederhana. Anda dapat menggunakan matriks yang benar untuk mendapatkan kembali vektor dengan panjang 52 dengan 5. Saya akan membiarkan Anda mencari tahu.
Yuval Filmus
13

nlgnlg2598960=22

Bagaimana cara kerja representasi? Ada berbagai opsi, dengan pengorbanan yang berbeda. Saya daftar dua di bawah ini.

Kamus kode-keras

Dalam hal ini, jumlah kartu 5 kartu yang mungkin cukup kecil sehingga Anda hanya bisa memiliki kamus kode keras yang mencantumkan semua kartu 2598960, dan Anda mewakili tangan dengan indeksnya di kamus (diwakili dalam biner).

Dengan kata lain, kamus dapat berupa daftar tangan yang diurutkan. Masing-masing tangan adalah 5-tupel kartu di tangan, dalam urutan diurutkan. Anda dapat mencari di kamus menggunakan pencarian biner dan menemukan indeks yang sesuai; dan diberi indeks, Anda dapat menemukan tangan yang sesuai. Atau, Anda dapat menyimpan kamus sebagai peta hash yang memetakan dari tangan ke indeksnya. Indeks adalah bilangan bulat antara 0 dan 2598959, sehingga dapat direpresentasikan menggunakan 23 bit.

Pendekatan ini akan bekerja dan sangat sederhana untuk diprogram, tetapi boros dalam ruang (ukuran program yang dapat dieksekusi).

Pemeringkatan / unranking

Atau, jika Anda peduli, ada metode yang lebih baik. Lihat, misalnya, salah satu referensi berikut:

Topik umum dikenal sebagai "peringkat (dan unranking) kombinasi". Ini sedikit lebih kompleks untuk diimplementasikan dan dipahami, tetapi hindari kebutuhan untuk memasukkan kamus kode-keras dalam program.

DW
sumber
Saya akan memperbarui pertanyaan. Ya ada 2598960 tangan. Kamus akan memiliki banyak baris. Masalah saya adalah pembuatan kunci. Dari 5 kartu saya perlu membuat kunci untuk melakukan pencarian kamus.
paparazzo
@ Paparazzi, jika Anda menggunakan pendekatan kamus, tangan adalah kuncinya. Dengan kata lain, kuncinya adalah 5-tupel kartu di tangan (dalam urutan diurutkan). Kamus dapat disimpan sebagai hashtable menggunakan itu sebagai kunci. Jika Anda tidak menyukai biaya memori kamus, gunakan pendekatan alternatif: peringkat / penghapusan tanda.
DW
Ya saya tahu saya bisa mendapatkan kunci 30 bit jika saya urutkan. Saya bertanya-tanya apakah ada cara untuk mendapatkan kunci 32 bit atau di bawah tanpa mengurutkan tuple 5 kartu. Saya akan melihat peringkat dan peringkat.
paparazzo
Saya tidak mengikuti peringkat / unranking tetapi terima kasih. Saya akan mencoba dan mencari tahu. Juga memiliki kemungkinan ikatan. Ada banyak ikatan.
paparazzo
1
Juga relevan: cs.stackexchange.com/questions/67664/…
Nama samaran
3

Anda dapat mengurutkan lima item dan secara bersamaan memeriksa duplikat tanpa perbandingan pada beberapa prosesor: Asumsikan prosesor memiliki instruksi cepat yang menentukan posisi set bit tertinggi, dan instruksi cepat menghitung angka dengan hanya set bit ke-n .

Biarkan bit (n) menjadi angka dengan set bit ke-n. Biarkan tertinggi_bit (x) menjadi jumlah bit tertinggi yang diatur dalam angka x, dengan nilai yang tidak ditentukan jika x = 0. Misalkan x ^ y menjadi eksklusif-atau dari x dan y.

Diberikan lima angka a, b, c, d dan e, masing-masing dari 0 hingga 51, mewakili lima kartu di tangan.

Biarkan x = bit (a) ^ bit (b) ^ bit (c) ^ bit (d) ^ bit (e).

Biarkan A = tertinggi_bit (x), ubah x menjadi x ^ bit (A).

Biarkan B = tertinggi_bit (x), ubah x menjadi x ^ bit (B).

Biarkan C = tertinggi_bit (x), ubah x menjadi x ^ bit (C).

Biarkan D = tertinggi_bit (x), ubah x menjadi x ^ bit (D).

Biarkan E = tertinggi_bit (x).

Jika x = 0 maka ada duplikat di nomor a, b, c, d, dan e. Kalau tidak, gunakan bit A * (24) + B * bit (18) + C * bit (12) + D * bit (6) + E sebagai pengodean tangan, di mana A, B, C, D, dan E didefinisikan seperti di atas. Ini mengkodekan tangan sebagai string 30-bit, sambil melakukan penyortiran dengan cara yang sangat efisien.

gnasher729
sumber
Apakah ini menggunakan 52 bit?
paparazzo
@ Paparazzi, tidak. Lihatlah paragraf terakhir. Saya mengeditnya untuk mencoba memberikan kejelasan yang lebih besar lagi.
DW
1
Ini membutuhkan CPU 64-bit, tetapi hasil akhirnya hanya 30 bit.
Yuval Filmus