5 kartlı poker elini temsil et


11

Bir kart destesi 52'dir. Bir el 52 karttan 5 karttır (kopya olamaz).

5 kartlı bir eli temsil edecek en az bit sayısı nedir ve nasıl?
Bir el siparişe bağlı DEĞİLDİR (KQ = QK). 64329 = 96432

Evet, 52 bit kullanabilir. Bu, herhangi bir sayıda kartın elini temsil edebilir.

Bir elin tam olarak 5 kart olduğu göz önüne alındığında, 52 bit'ten az ile onu temsil etmenin bir yolu vardır.

Tek bir kart 6 bit = 64 ile temsil edilebilir. Bu yüzden sadece 6 bit * 5 kart = 30 bit kullanabilirsiniz. Ancak bu düzene bağlı olacaktır. Sadece sıralayabilirim ve bu işe yaramalı. Bu işe yaramazsa lütfen bana bildirin.

32 bit veya daha düşük bir anahtar almak için bir yol var mı ve 5 kart demet sıralamak zorunda değilsiniz.

Bu poker simülasyonları içindir ve sıralama sadece eli üretmeye kıyasla çok fazla yük olurdu. Her elin göreceli değeri olan bir sözlüğüm varsa, iki basit arama ve iki elin değerini karşılaştırmak için bir karşılaştırma. Önce iki sıralamaya ve bir karşılaştırmaya kıyasla büyük olan elleri sıralamam gerekiyorsa. Bir simülasyonda milyonları karşılaştıracağız. Simülasyondan el ele geçirilmeyeceğim. Sıralama 52 51 50 49 48 gibi 52 51 50 49 48 gibi basit değil. Düz floş dörtlü olabilir ....

2598960 olası 5 kart eli vardır. Sıra sayısı budur. Anahtar 5 karttır. 32 bit veya kartların önce sıralanmasına gerek olmayan bir anahtar almak istiyorum.

Sadece el kravat olarak listeyi sipariş edemezsiniz. Takım elbise maça, kulüp, elmas ve kalp. 7c 8c 2d 3d 4s = 7s 8s 2c 3c 4h. Çok sayıda bağ var.

Bir sonraki adım 64 bittir ve anahtarın boyutunu iki kat yerine sıralamanın ismini alacaktır.

SortedSet<int> quickSort = new SortedSet<int>() { i, j, k, m, n };İşlem süresini test ettim ve iki katına çıkardım ama yine de yapabilirim.

Daha karmaşık hale geliyor. Bir tekneyi beş üzerinden iki kez temsil edebilmem gerekiyor (22255). Yani onları ayırmak onu kırar. Söyleyeceğini biliyorum ama bu hızlı. Evet hızlı ve önemsiz ama olabildiğince hızlı ihtiyacım var.

Kabul edilen cevap için 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
Uzunluk listelerini sıralamak için çalışan, elle kodlanmış bir sıralama algoritması kullanın. Bu, muhtemelen şu anda kullanmakta olduğunuz kütüphane işlevinden daha hızlıdır.
Yuval Filmus

1
"Sıra basit değil" dediğini anlamıyorum . Sıralama olan basit - elle kart (uzunluk 5) bir listesi ile temsil edilir, böylece, 1 ila 52'ye bir sayı, her bir kart dönüştürün. Bu listeyi sıralayın. Bu, Yuval'ın belirttiği gibi, çok hızlı bir şekilde yapılabilecek 5 tamsayı bir listeyi sıralama problemidir. Çok yavaş olduğunu varsaymadan önce ölçmenizi öneririm, ama tahminimce böyle bir listeyi sıralamak çok hızlı olacak ve hatta önbellekte bulunmayan rastgele erişimli bir bellek okumasından daha hızlı olabilir.
DW

@dw Evet sıralama basit ama yaptığım şey (milyonlarca kez) basit. Test ettim ve bir çeşit zaman iki katına çıktı.
paparazzo

1
@Paparazzi Hayır, Yuval, 1 ile 52 arasında beş sayıyı sıralamak için özel olarak ayarlanmış kendi sıralama rutininizi yazmanızı söylüyor. Bu kütüphane rutinini kullanmayı denediniz, çünkü bu daha genel ve tekrarlayan doğa nedeniyle quicksort kısa listelerde çok verimsiz yapar.
David Richerby

Pratikte, <= 16 bit olmayan öğelerin çoğu 32 bit olabilir. Bu nedenle, en az 23 bite ihtiyacınız olduğundan, <= 32 bit kullanan herhangi bir kodlama muhtemelen uygulanabilir. Kart başına önemsiz 6 bit * 5 kart kodlaması yeterince iyi çalışıyor. Bir uyarı var: 23 bit dizi dizini 32 bit dizi dizininden çok daha iyi.
MSalters

Yanıtlar:


10

Let bir olmak [ . Bunu kullanarak elinizi a , b , c , d , e kodlayabilirsinizC kodu. Parite kontrol matrisi C a, 27 x 52 sütun XOR kaybolur minimal sayısı olduğu biraz matrisi, 11 . 52 sütunu A 1 , , A 52 ile gösterin. Her belirleyebilir A i uzunluğu bir ikili sayı olarak 27 bit. Bu sayıların 1 ila 10'unun XORdeğeri asla 0 değildir.[52,25,11]C27x521152bir1,...,bir52birben271100bir,b,c,d,e olarak , XOR olduğunu. Nitekim, açıkça bu sıraya bağlıdır ve olmazsa iki el H 1 , H 2 çarpışır, sonra da iki karma değerlerini xoring verir 10 - 2 | H 1H 2 | 10 olan XOR numaraları sıfırdır.birbirbirbbircbirdbire'H1,'H210-2|'H1'H2|10

Bob Jenkins sitesinde böyle bir kod açıklıyor ve bundan diziyi çıkarabiliriz

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


Tam olarak takip etmiyorum. Bunun bir el için kaç bit ihtiyacı var?
paparazzo

27 bite ihtiyacı var. Daha fazla sayıda bit kullanabilirsiniz.
Yuval Filmus

Teşekkürler. Test ettim ve sayılar benzersiz ve <= 32 bit. 5 kartı numaradan çıkarabilir miyim? İyi değilse sadece soruyorum.
paparazzo

Evet, basit doğrusal cebir. 52 olan bir vektörü 5 olanla geri almak için doğru matrisi kullanabilirsiniz. Bunu çözmene izin vereceğim.
Yuval Filmus

13

nlgnlg2598960=22

Temsil nasıl çalışır? Farklı ödünç verme özelliklerine sahip çeşitli seçenekler vardır. Aşağıda iki tane listeliyorum.

Sabit kodlu sözlük

Bu durumda, olası 5 kartlı el sayısı, 2598960 elin tümünü listeleyen sabit kodlu bir sözlüğe sahip olabileceğiniz kadar küçüktür ve bir eli sözlükteki dizinine göre (ikili olarak temsil edilir) temsil edersiniz.

Başka bir deyişle, sözlük sıralı bir el listesi olabilir. Her el, eldeki kartların sıralı olarak 5 demetidir. İkili aramayı kullanarak sözlükte bir el arayabilir ve karşılık gelen dizinini bulabilirsiniz; ve bir indeks verildiğinde ilgili eli bulabilirsiniz. Veya sözlüğü elden dizinine eşleyen bir hashmap olarak saklayabilirsiniz. Dizin, 0 ile 2598959 arasında bir tamsayıdır, bu nedenle 23 bit kullanılarak temsil edilebilir.

Bu yaklaşım işe yarayacak ve programlanması çok basit olacaktır, ancak uzayda boşa harcanır (programın yürütülebilir boyutu).

Sıralama / unranking

Alternatif olarak, önemsiyorsanız, daha iyi yöntemler vardır. Aşağıdaki referanslardan herhangi birine bakınız:

Genel konu "kombinasyonların sıralaması (ve unranking)" olarak bilinir. Bunlar, uygulanması ve anlaşılması biraz daha karmaşıktır, ancak programa sabit kodlu bir sözlük ekleme ihtiyacını ortadan kaldırır.


Soruyu güncelleyeceğim. Evet 2598960 el var. Sözlük o kadar çok satıra sahip olacak. Benim sorunum anahtarın üretilmesidir. 5 karttan sözlük araması yapmak için bir anahtar üretmem gerekiyor.
paparazzo

@Paparazzi, sözlük yaklaşımını kullanırsanız, el olduğunu tuşu. Başka bir deyişle, anahtar eldeki kartların 5 sıralı halidir (sıralı olarak). Sözlük, anahtar olarak kullanılarak bir hashtable olarak saklanabilir. Bir sözlüğün bellek maliyetlerinden hoşlanmıyorsanız, alternatif yaklaşımı kullanın: sıralama / unranking.
DW

Evet, sıralarsam 30 bitlik anahtarı alabilirim. 5 kart demetini ayırmadan 32 bit veya daha düşük bir anahtar almanın bir yolu olup olmadığını merak ediyorum. Rütbe ve sıralamaya bakacağım.
paparazzo

Ben sıralama / unranking takip değil ama teşekkürler. Bunu anlamaya çalışacağım. Aynı zamanda bağların olanakları var. Bir sürü bağ var.
paparazzo


3

Beş öğeyi sıralayabilir ve eşzamanlı olarak bazı işlemcilerde herhangi bir karşılaştırma yapmadan kontrol edebilirsiniz: İşlemcinin en yüksek bit kümesinin konumunu belirleyen hızlı bir talimatı ve yalnızca n. Bit kümesiyle bir sayıyı hesaplayan hızlı bir talimatı olduğunu varsayın .

Bit (n), tam olarak n. Th bit ayarlanmış sayı olsun. En yüksek_bit (x), x = 0 ise, belirtilmemiş bir değere sahip, x sayısında ayarlanan en yüksek bitin sayısı olsun. X ^ y özel-veya x ve y olsun.

Verilen, eldeki beş kartı temsil eden, her biri 0'dan 51'e kadar olan beş sayı a, b, c, d ve e'dir.

X = bit (a) ^ bit (b) ^ bit (c) ^ bit (d) ^ bit (e) olsun.

A = en yüksek_bit (x) olsun, x'i x ^ bit (A) olarak değiştirin.

B = en yüksek_bit (x) olsun, x'i x ^ bit (B) olarak değiştirin.

C = en yüksek_bit (x) olsun, x'i x ^ bit (C) olarak değiştirin.

D = en yüksek_bit (x) olsun, x'i x ^ bit (D) olarak değiştirin.

E = en yüksek_bit (x) olsun.

X = 0 ise, a, b, c, d ve e sayılarında kopyalar vardı. Aksi takdirde, elin kodlaması olarak A * bit (24) + B * bit (18) + C * bit (12) + D * bit (6) + E kullanın; burada A, B, C, D ve E yukarıdaki gibi tanımlanmıştır. Bu, sıralamayı çok verimli bir şekilde yaparken bir eli 30 bit dize olarak kodlar.


Bu 52 bit kullanıyor mu?
paparazzo

@Paparazzi, hayır. Son paragrafa tekrar bakın. Daha da fazla netlik sağlamak için düzenledim.
DW

1
64 bit CPU gerektirir, ancak sonuç sadece 30 bittir.
Yuval Filmus
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.