Als alternative Lösung für dieses Problem verwendet mein Algorithmus zusammengesetzte gebrochene (nicht ganzzahlige) Bits pro Karte für Gruppen von Karten im Stapel, basierend auf der Anzahl der verbleibenden unbesetzten Ränge. Es ist ein ziemlich eleganter Algorithmus. Ich habe meinen Codierungsalgorithmus von Hand überprüft und er sieht gut aus. Der Encoder gibt scheinbar korrekte Bitstrings aus (der Einfachheit halber in Byte-Form).
Der Überblick über meinen Algorithmus ist, dass er eine Kombination aus Kartengruppen und zusammengesetzter fraktionierter Bitcodierung verwendet. Zum Beispiel in meiner gemeinsamen Testdatei von Mio. schlurfte Decks, hat die ersten , die ersten 7 Karten von 54 A 236 J . Ich habe mich für eine Blockgröße von 7 Karten entschieden, wenn 13 Kartenreihen möglich sind, weil 13 7 "Schuhlöffel" (genau passend) in 26 Bits passen (da 13 7 = 62 , 748 , 517 und 2 26 = 67 , 108) .3754 A 236 J7131372613762 , 748 , 517226 ). Idealerweise möchten wir, dass diese beiden Zahlen so nah wie möglich sind (aber mit der Potenz von 2 Zahlen etwas höher), damit wir beim Bit-Packen nicht mehr als einen sehr kleinen Bruchteil eines Bits verschwenden. Hinweis: Ich hätte auch die Gruppengröße 4 wählen können,wennich 13 Rängecodiert hätte,da 13 4 = 28 , 561 und 2 15 = 32 , 768 . Es ist nicht so eng ein Sitz seit 15 / 4 = 3,75 , aber 26 / 7 = 3,71467 , 108 , 864241313428 , 56121532 , 76815 / 4 = 3,7526 / 7 = 3.714. Daher ist die Anzahl der Bits pro Karte etwas geringer, wenn wir die Packungsmethode verwenden.26 / 7
So betrachten , wir einfach die Ordnungsposition dieser Reihen in unserem Master „nachzuschlagen 23456789 T J Q K A “ Liste der sortierten Reihen. Beispielsweise hat der erste tatsächliche Kartenrang von 5 eine Suchposition in der Rangfolge von 4 . Wir behandeln diese 7 Rangpositionen einfach als eine Basis- 13- Zahl, die mit 0 beginnt (die Position 4, die wir zuvor erhalten haben, ist also tatsächlich eine 3). Zurück zur Basis 10 konvertiert (zu Überprüfungszwecken), erhalten wir 15 , 565 , 975 . In 2654 A 236 J23456789 TJQ. KEIN547131015 , 565 , 97526Bits der Binärdatei erhalten wir .00111011011000010010010111
Der Decoder arbeitet sehr ähnlich. Es nimmt (zum Beispiel) diese Zeichenkette von Bits und konvertiert sie zurück in eine Dezimalzahl (Basis 10), um 15 , 565 , 975 zu erhalten , konvertiert sie dann in eine Basis 13 , um die Offsets in die Rangnachschlagzeichenkette zu bekommen, und rekonstruiert dann die Ränge eine nach der anderen und erhält die ursprünglichen 54 A 236 J ersten 7 Karten. Beachten Sie, dass die Blockgröße der Bits nicht immer 26 ist, sondern immer bei 26 in jedem Deck beginnt. Sowohl der Encoder als auch der Decoder verfügen bereits vor dem Betrieb über wichtige Informationen zu den Deckdaten. Das ist eine außergewöhnlich schöne Sache an diesem Algorithmus.2615 , 565 , 9751354 A 236 J7
Jede Anzahl der Reihen verbleibenden (wie etwa hat seine eigene Gruppengrße und die Kosten (Anzahl der Bits pro Karte). Diese wurden experimentell gefunden, indem sie nur mit Potenzen von 13 , 12 , 11 und 2 gespielt haben . Ich habe bereits erklärt, wie ich die Gruppengröße erhalten habe, wenn wir 13 Ränge sehen können. Wie wäre es also, wenn wir auf 12 unbesetzte Ränge fallen? Gleiche Methode. Schauen Sie sich die Potenzen von 12 an und hören Sie auf, wenn eine von ihnen einer Potenz von 2 sehr nahe kommt, aber nur geringfügig darunter liegt. 13 , 12 , 11 . . . , 2 , 1 )13 , 12 , 11 ...21312122 = 248 , 832 und 2 18 = 262 , 144 . Das ist eine ziemlich enge Passform. Die Anzahl der Bits dieser Gruppe kodiertist 18 / 5 = 3,6 . In der 13 RankGruppe war es 26 / 7 = 3,714 , so wie Sie sehen können, wie die Zahl der offenen Reihen abnimmt (Reihen füllen sich wie 5555 , 3333 ), die Anzahl der Bitsdie Karten zu kodieren abnimmt.125248 , 832218262 , 14418 / 53.61326 / 73,71455553333
Hier ist meine vollständige Liste der Kosten (Anzahl der Bits pro Karte) für alle möglichen Ränge:
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. Wenn das Deck mit einem Paar (wie 77), einem Triple / Set (wie 777) oder einem Quad (wie 7777) endet, erhalten wir mit meinem Algorithmus zusätzliche Einsparungen für dieses Deck.
3222613163232
Im ersten Deck der Datendatei ist die Kodierung der Karten wie folgt (Diagramm folgt später). Das Format ist (Gruppengröße, Bits, Rangcodierungsmodus):
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 ...322223333444455556666777788889999 TTTTJJJJQ Q Q Q KKKKA A A A40
1103 , 7K8101Verbleibende Karte. Dies ist wichtig, da es den Codierungsprozess effizienter macht, wenn der Decodierer korrekte Annahmen treffen kann, ohne dass der Codierer zusätzliche Nachrichten an ihn übergeben muss.
313121110
26 26 26 18 18 10 9 17 13 5 0
54 A 236 J 87726 Q 3 3969 A A A Q JK7 T 9292 Q 36 K J57 T 8 TKJ4 48 Q 8 T 55 K 4
13 12 x y 98 7 6 543 2 1 0
2166175168Bits. Beachten Sie, dass wir nur eine einzelne 4 am Ende des Decks haben, aber wenn wir stattdessen alle vier 4en dort haben, ist das ein besserer Fall und wir hätten nur 161 Bits benötigt, um dieses Deck zu kodieren, ein Fall, in dem die Packung tatsächlich die schlägt Entropie einer geraden binären Kodierung ihrer Ordnungsposition.
Ich habe jetzt den Code implementiert, um die Bitanforderungen zu berechnen, und er zeigt mir durchschnittlich etwa 175 Bits pro Deck mit einem Tief von 155 und einem Hoch von 183 für die 3-Millionen-Deck-Testdatei. Mein Algorithmus scheint also 9 zusätzliche Bits pro Deck zu verwenden, verglichen mit der geraden binären Codierung der Ordinalpositionsmethode. Nicht schlecht bei nur 5,5% zusätzlichem Speicherplatzbedarf. 176 Bits sind genau 22 Bytes, das ist also deutlich besser als 52 Bytes pro Deck. Best-Case-Deck (nicht in 3 Millionen Deck-Testdateien enthalten) Packs mit 136 Bit und Worst-Case-Deck (8206-mal in Testdateien enthalten) mit 183 Bit. Die Analyse zeigt, dass der schlimmste Fall darin besteht, dass wir das erste Quad erst in der Nähe von (oder bei) Karte 40 erhalten. Da der Codierungsmodus dann schnell abfallen soll, bleiben wir beim Füllen von Blöcken (bis zu 7 Karten) in a stecken höherer Bitcodierungsmodus. Man könnte meinen, dass es mit einem gut gemischten Deck ziemlich selten sein würde, keine Quads bis Karte 40 zu bekommen, aber mein Programm sagt mir, dass es 321-mal in der Testdatei von 3 Millionen Decks passiert ist, so dass es ungefähr 1 von 9346 Decks ist. Das ist öfter so, als ich erwartet hätte. Ich könnte nach diesem Fall suchen und es mit weniger Bits behandeln, aber es ist so selten, dass es die durchschnittlichen Bits nicht genug beeinflusst.
Auch hier ist noch etwas sehr Interessantes. Wenn ich das Deck nach den Rohdaten des Decks sortiere, beträgt die Länge der Präfixe, die eine signifikante Anzahl von Malen wiederholen, nur ungefähr 6 (wie z. B. 222244). Mit den gepackten Daten erhöht sich diese Länge jedoch auf ungefähr 16. Das heißt, wenn ich die gepackten Daten sortiere, sollte es mir möglich sein, erhebliche Einsparungen zu erzielen, indem ich dem Decoder nur ein 16-Bit-Präfix anzeige und dann nur den Rest der Decks ausgebe (abzüglich des sich wiederholenden Präfixes), die dasselbe Präfix haben, dann gehe zum nächsten Präfix und wiederhole es. Angenommen, ich spare auf diese Weise nur 10 Bit pro Deck, dann sollte ich die 166 Bit pro Deck schlagen. Bei der von anderen angegebenen Aufzählungstechnik bin ich mir nicht sicher, ob das Präfix so lang wäre wie bei meinem Algorithmus. Auch die Pack- und Entpackgeschwindigkeit mit meinem Algorithmus ist überraschend gut.
Bezüglich der 2. Komprimierungsstufe, in der ich die Ausgabebitstrings meines Algorithmus sortiere, verwende ich dann die "Differenz" -Codierung: Eine sehr einfache Methode wäre, die 61.278 eindeutigen 16-Bit-Präfixe zu codieren, die in den Ausgabedaten mindestens zweimal (und maximal zweimal) vorkommen von 89 mal gemeldet) einfach als führendes Bit von 0 in der Ausgabe, um dem Dekomprimierer der 2. Ebene anzuzeigen, dass wir ein Präfix (z. B. 0000111100001111) codieren, und dann werden alle gepackten Decks mit demselben Präfix mit einem führenden Bit von 1 bis folgen Geben Sie den Nicht-Präfix-Teil des gepackten Decks an. Die durchschnittliche Anzahl gepackter Decks mit demselben Präfix liegt bei 49 für jedes Präfix, ohne die wenigen, die eindeutig sind (nur 1 Deck hat dieses bestimmte Präfix). Es sieht so aus, als könnte ich mit dieser einfachen Strategie etwa 15 Bits pro Deck einsparen (die gemeinsamen Präfixe einmal speichern).
Nach der 2. Komprimierungsstufe unter Verwendung der Differenzcodierung (Präfixcodierung) der sortierten Bitstring-Ausgabe des ersten Codierers erhalte ich jetzt ungefähr 160 Bits pro Deck. Ich verwende das Präfix für Länge 18 und speichere es einfach intakt. Da fast alle (245013 von 262144 = 93,5%) dieser möglichen 18-Bit-Präfixe angezeigt werden, ist es sogar besser, die Präfixe zu codieren. Vielleicht kann ich 2 Bits verwenden, um zu codieren, welche Art von Daten ich habe. 00 = reguläre Länge 18 Präfix gespeichert, 01 = "1 aufwärts Präfix" (wie vorheriges Präfix, außer 1 hinzugefügt), 11 = gerade Codierung aus 1st Level Packing (durchschnittlich ca. 175 Bit). 10 = zukünftige Erweiterung, wenn ich an etwas anderes denke, um zu kodieren, das Bits speichert.
Hat noch jemand 160 Bit pro Deck geschlagen? Ich denke, ich kann meine mit einigem Experimentieren und Verwenden der 2-Bit-Deskriptoren, die ich oben erwähnt habe, ein wenig senken. Vielleicht fällt es bei 158ish aus. Mein Ziel ist es, 156 Bit (oder besser) zu erreichen, da dies 3 Bit pro Karte oder weniger sind. Sehr beeindruckend. Es wird viel experimentiert, um dieses Niveau zu erreichen, denn wenn ich die Kodierung der ersten Ebene ändere, muss ich erneut testen, welche Kodierung die beste Kodierung der zweiten Ebene ist, und es gibt viele Kombinationen, die ich ausprobieren kann. Einige Änderungen, die ich vornehme, sind möglicherweise für andere ähnliche zufällige Daten geeignet, andere sind jedoch möglicherweise auf diesen Datensatz ausgerichtet. Ich bin mir nicht sicher, aber wenn ich den Drang bekomme, kann ich einen weiteren 3-Millionen-Deck-Datensatz ausprobieren, um zu sehen, wie es passiert, wenn ich ähnliche Ergebnisse erhalte.
1050
Hat jemand eine Idee, wie ich meinen Algorithmus so verbessern kann, wie es in anderen Fällen der Fall ist, in denen ich durchschnittlich weniger Speicherplatz für jedes Deck benötige? Jemand?
2 weitere Dinge: 1) Ich bin etwas enttäuscht, dass mehr Leute meine Lösung nicht positiv bewertet haben, die zwar nicht optimal ist, aber dennoch anständig und relativ einfach zu implementieren ist (ich habe meine gut funktionieren lassen). 2) Ich habe meine 3-Millionen-Deck-Datendatei analysiert und festgestellt, dass die am häufigsten vorkommende Karte, bei der der erste Rang belegt ist (z. B. 4444), auf Karte 26 liegt. Dies passiert in etwa 6,711% der Fälle (für 201322 der 3 Millionen Decks) ). Ich hatte gehofft, diese Informationen zu verwenden, um mehr zu komprimieren, wie zum Beispiel im 12-Symbol-Codierungsmodus zu beginnen, da wir im Durchschnitt nicht jeden Rang bis etwa zur Mitte des Decks sehen, aber diese Methode konnte keinen komprimieren, da der Overhead die Einsparungen überschritt. Ich suche nach einigen Verbesserungen an meinem Algorithmus, die tatsächlich Bits sparen können.
Hat jemand eine Idee, was ich als nächstes versuchen sollte, um mit meinem Algorithmus ein paar Bits pro Deck zu sparen? Ich suche nach einem Muster, das häufig genug vorkommt, damit ich die Bits pro Deck reduzieren kann, selbst nachdem ich dem Decoder zusätzlich mitteilte, welches Muster zu erwarten ist. Ich überlegte mir etwas mit den erwarteten Wahrscheinlichkeiten der verbleibenden unsichtbaren Karten und füllte alle verbleibenden Einzelkarten in einen einzigen Eimer. Dadurch kann ich schneller in einen niedrigeren Codierungsmodus wechseln und möglicherweise ein paar Bits sparen, aber ich bezweifle es.
Außerdem habe ich zur Vereinfachung der Analyse 10 Millionen Zufallsmischungen generiert und in einer Datenbank gespeichert. Nur 488 von ihnen enden in einem Quad (wie 5555). Wenn ich nur die packe, die meinen Algorithmus verwenden, erhalte ich durchschnittlich 165,71712 Bits mit einem Tief von 157 Bits und einem Hoch von 173 Bits. Nur etwas unter den 166 Bits bei der anderen Codierungsmethode. Ich bin etwas überrascht, wie selten dieser Fall ist (durchschnittlich etwa 1 von 20.492 Shuffles).