Jako alternatywne rozwiązanie tego problemu, mój algorytm używa złożonych ułamkowych bitów (niecałkowitych) na kartę dla grup kart w talii w oparciu o liczbę pozostałych niewypełnionych szeregów. Jest to dość elegancki algorytm. Sprawdziłem ręcznie mój algorytm kodowania i wygląda dobrze. Koder wyprowadza coś, co wydaje się być poprawnym ciągiem bitów (dla uproszczenia w formie bajtów).
3754A236J7131372613762,748,51722667,108,864241313428,56121532,76815/4=3.7526/7=3.71426/7
54A236J23456789TJQKA547131015,565,9752600111011011000010010010111
2615,565,9751354A236J7
13,12,11...,2,1)13,12,11...21312122125248,832218262,14418/53.61326/73.71455553333
Oto moja pełna lista kosztów (liczba bitów na kartę) dla wszystkich możliwych # rang do wyświetlenia:
13 26/7=3.714=3 5/7
12 18/5=3.600=3 3/5
11 7/2=3.500=3 1/2
10 10/3=3.333=3 1/3
9 16/5=3.200=3 1/5
8 3/1=3.000=3
7 17/6=2.833=2 5/6
6 13/5=2.600=2 3/5
5 7/3=2.333=2 1/3
4 2/1=2.000=2
3 5/3=1.667=1 2/3
2 1/1=1.000=1
1 0/1..4=0.0=0
75,6,7,7,7,7,KK1312713K21,2,3...3131720
16813,12,11
10777748747s. Jeśli talia kończy się na parze (np. 77), potrójnej / secie (np. 777) lub quadzie (np. 7777), uzyskujemy dodatkowe oszczędności dla tej talii przy użyciu mojego algorytmu.
3222613163232
W pierwszej talii w pliku danych kodowanie kart wygląda następująco (schemat pojawi się później). Format to (tryb grupowania, bitów, kodowania rang):
7,26,1372613
7,26,13
7,26,13
5,18,12
5,18,12
3,10,10
3, 9, 8
6,17, 7
5,13, 6
3, 5, 3
1, 0, 1
521683.23
181/33.23.254545454722772277...322223333444455556666777788889999TTTTJJJJQQQQKKKKAAAA40
1103,7K8101karta pozostała. Jest to ważne, ponieważ sprawia, że proces kodowania jest bardziej wydajny, gdy dekoder może przyjmować prawidłowe założenia bez konieczności przesyłania przez koder dodatkowych komunikatów.
313121110
54 A 236 J 87726 Q 3 3969 A A A Q J K 7 T 9292 Q 36 K J 26 26 26 18 18 10 9 17 13 5 0
54A236J 87726Q3 3969AAA QJK7T 9292Q 36K J57 T8TKJ4 48Q8T 55K 4
13 12 xy 98 7 6 543 2 1 0
2166175168bitów Zauważ, że mamy tylko jeden 4 na końcu talii, ale jeśli zamiast tego mamy tam wszystkie cztery 4, to jest lepszy przypadek i potrzebowalibyśmy tylko 161 bitów do zakodowania tej talii, przypadek, w którym opakowanie faktycznie pokonuje entropia prostego kodu binarnego jego pozycji porządkowej.
Teraz mam zaimplementowany kod do obliczania wymagań bitowych i pokazuje mi on średnio około 175 bitów na talię z niskim 155 i wysokim 183 dla pliku testowego z 3 milionami talii. Więc mój algorytm wydaje się używać 9 dodatkowych bitów na talię w porównaniu z prostym kodem binarnym metody pozycji porządkowej. Nieźle jak na tylko 5,5% dodatkowej przestrzeni dyskowej. 176 bitów to dokładnie 22 bajty, więc jest to nieco więcej niż 52 bajty na talię. Najlepsza talia (nie pokazała się w 3 milionach plików testowych) paczki do 136 bitów, a najgorsza talia (pokazała się w pliku testowym 8206 razy), to 183 bity. Analiza pokazuje, że najgorszym przypadkiem jest sytuacja, w której pierwszy kwadrant nie zbliża się do karty 40 (lub w jej pobliżu). Następnie, gdy tryb kodowania chce szybko spaść, blokujemy wypełnianie bloków (nawet 7 kart) wyższy tryb kodowania bitów. Można by pomyśleć, że nie otrzymanie żadnych quadów, dopóki karta 40 nie byłaby rzadka przy użyciu dobrze potasowanej talii, ale mój program mówi mi, że zdarzyło się to 321 razy w pliku testowym 3 milionów talii, tak że jest to około 1 na 9346 talii. Tak często się spodziewałam. Mógłbym sprawdzić ten przypadek i obsłużyć go mniejszą ilością bitów, ale jest to tak rzadkie, że nie wpłynęłoby to wystarczająco na średnią liczbę bitów.
Również tutaj jest coś bardzo interesującego. Jeśli posortuję talię na podstawie surowych danych talii, długość prefiksów, które powtarzają znaczącą liczbę razy, wynosi tylko około 6 (na przykład 222244). Jednak w przypadku spakowanych danych ta długość wzrasta do około 16. Oznacza to, że jeśli posortuję spakowane dane, powinienem być w stanie uzyskać znaczne oszczędności, po prostu wskazując dekoderowi 16-bitowy prefiks, a następnie po prostu wyprowadzając resztę talii (minus powtarzający się prefiks), które mają ten sam prefiks, a następnie przejdź do następnego prefiksu i powtórz. Zakładając, że w ten sposób zaoszczędzę nawet 10 bitów na talię, powinienem pokonać 166 bitów na talię. Dzięki technice wyliczania podanej przez innych nie jestem pewien, czy prefiks będzie tak długi, jak w przypadku mojego algorytmu. Również szybkość pakowania i rozpakowywania przy użyciu mojego algorytmu jest zaskakująco dobra.
Jeśli chodzi o drugi poziom kompresji, w którym sortuję wyjściowe ciągi bitów mojego algorytmu, a następnie używam kodowania „różnicowego”: bardzo prostą metodą byłoby zakodowanie 61 278 unikalnych 16-bitowych prefiksów, które pojawiają się co najmniej dwa razy w danych wyjściowych (i maksimum z 89 razy zgłoszonych) po prostu jako wiodący bit 0 na wyjściu, aby wskazać dekompresorowi drugiego poziomu, że kodujemy prefiks (taki jak 0000111100001111), a następnie wszystkie upakowane talie z tym samym prefiksem będą poprzedzone 1 bitem wiodącym do wskazuje nieprzedrostkową część zapakowanego pokładu. Średnia liczba spakowanych talii z tym samym prefiksem wynosi około 49 dla każdego prefiksu, nie licząc kilku unikalnych (tylko 1 talia ma ten konkretny prefiks). Wygląda na to, że mogę zaoszczędzić około 15 bitów na talię, korzystając z tej prostej strategii (zapamiętywanie wspólnych prefiksów raz).
Po 2. poziomie kompresji przy użyciu kodowania różnicowego (przedrostka) posortowanego wyjścia łańcucha bitów pierwszego enkodera, teraz otrzymuję około 160 bitów na talię. Używam prefiksu o długości 18 i po prostu przechowuję go w nienaruszonym stanie. Ponieważ pojawiają się prawie wszystkie (245013 z 262144 = 93,5%) z tych możliwych 18-bitowych prefiksów, byłoby jeszcze lepiej zakodować prefiksy. Być może mogę użyć 2 bitów do zakodowania, jaki typ danych mam. 00 = zapisany prefiks 18 o regularnej długości, 01 = „1 prefiks w górę” (taki sam jak poprzedni prefiks z wyjątkiem 1 dodanego), 11 = kodowanie proste z pakowania pierwszego poziomu (średnio około 175 bitów). 10 = przyszłe rozszerzenie, gdy myślę o czymś innym do zakodowania, co pozwoli zaoszczędzić bity.
Czy ktoś jeszcze pobił 160 bitów na talię? Wydaje mi się, że mogę trochę obniżyć moje, eksperymentując i używając 2-bitowych deskryptorów, o których wspomniałem powyżej. Być może osiągnie dno przy 158ish. Moim celem jest uzyskanie go do 156 bitów (lub lepiej), ponieważ byłoby to 3 bity na kartę lub mniej. Bardzo imponujące. Dużo eksperymentów, aby sprowadzić go do tego poziomu, ponieważ jeśli zmienię kodowanie pierwszego poziomu, muszę ponownie przetestować, które jest najlepszym kodowaniem drugiego poziomu i jest wiele kombinacji do wypróbowania. Niektóre zmiany, które wprowadzam, mogą być dobre dla innych podobnych danych losowych, ale niektóre mogą być tendencyjne w stosunku do tego zestawu danych. Nie jestem do końca pewien, ale jeśli przyjdzie mi ochota, mogę wypróbować kolejny 3 milionowy zestaw danych pokładowych, aby zobaczyć, co się stanie, jeśli otrzymam podobne wyniki.
1050
Czy ktoś ma jakieś pomysły, jak ulepszyć mój algorytm, jak inne przypadki, które powinienem zakodować, co zmniejszyłoby ilość pamięci dla każdej talii? Ktoś?
Jeszcze 2 rzeczy: 1) Jestem nieco rozczarowany, że więcej osób nie głosowało za moim rozwiązaniem, które choć nie jest optymalne w przestrzeni, jest przyzwoite i dość łatwe do wdrożenia (moje działa dobrze). 2) Przeprowadziłem analizę mojego pliku danych z 3 milionami talii i zauważyłem, że najczęściej występującą kartą, w której wypełnia się 1. stopień (np. 4444), jest karta 26. Zdarza się to około 6,711% czasu (dla 201322 z 3 milionów talii ). Miałem nadzieję, że wykorzystam te informacje do skompresowania większej ilości danych, takich jak start w trybie kodowania 12 symboli, ponieważ wiemy, że średnio nie zobaczymy każdej rangi aż do około połowy pokładu, ale ta metoda nie kompresowała żadnego, ponieważ narzut przekroczył oszczędności. Szukam kilku poprawek w moim algorytmie, które mogłyby faktycznie zaoszczędzić bity.
Czy ktoś ma jakieś pomysły, co powinienem spróbować, aby zaoszczędzić kilka bitów na talię za pomocą mojego algorytmu? Szukam wzoru, który zdarza się wystarczająco często, żebym mógł zmniejszyć liczbę bitów na talię, nawet po dodatkowym obciążeniu wynikającym z powiedzenia dekoderowi, jakiego wzoru się spodziewać. Myślałem coś z oczekiwanymi prawdopodobieństwami pozostałych niewidzialnych kart i wrzucałem wszystkie pozostałe pojedyncze karty do jednego wiadra. Pozwoli mi to szybciej przejść do niższego trybu kodowania i być może zaoszczędzę trochę bitów, ale wątpię w to.
Ponadto, FYI, wygenerowałem 10 milionów losowych przetasowań i zapisałem je w bazie danych w celu łatwej analizy. Tylko 488 z nich kończy się na quadzie (np. 5555). Jeśli spakuję tylko te, które używają mojego algorytmu, otrzymam średnio 165,71712 bitów z niskim 157 bitów i wysokim 173 bitów. Nieco nieco poniżej 166 bitów przy użyciu innej metody kodowania. Jestem nieco zaskoczony, jak rzadka jest ta sprawa (średnio około 1 na każde 20 492 przetasowań).