Können zufällige, ungeeignete


19

Ich habe echte Daten, die ich für ein simuliertes Kartenspiel verwende. Ich interessiere mich nur für die Reihen der Karten, nicht für die Farben. Da es sich jedoch um ein Standardkartenspiel mit 52 Karten handelt, sind im Kartenspiel nur 4 Ränge möglich. Das Deck wird für jede Hand gut gemischt, und dann gebe ich das gesamte Deck in eine Datei aus. Es gibt also nur 13 mögliche Symbole in der Ausgabedatei, die 2,3,4,5,6,7,8,9,T,J,Q,K,A . ( T= zehn Rang). Natürlich können wir diese mit 4 Bits pro Symbol bitpacken , aber dann verschwenden wir 3 der 16 möglichen Codierungen. Wir können es besser machen, wenn wir 4 Symbole gleichzeitig gruppieren und dann komprimieren, weil 134 = 28,561 und das kann eher "eng" in 15 Bits statt passen 16. Das theoretische Bitpack-Limit ist log ( 13 ) / log ( 2 ) = 3.70044 für Daten mit 13 zufälligen Symbolen für jede mögliche Karte. Wir können jedoch keine 52Könige zum Beispiel in diesem Deck. Wir MÜSSEN nur 4 von jedem Rang in jedem Deck haben, so dass die Entropiecodierung um ungefähr ein halbes Bit pro Symbol auf ungefähr abfällt 3.2.

Ok, also hier ist was ich denke. Diese Daten sind nicht völlig zufällig. Wir wissen, dass es 4 von jedem Rang gibt, also in jedem Block von 52 Karten (nennen wir es ein gemischtes Deck), so dass wir verschiedene Annahmen und Optimierungen vornehmen können. Eine davon ist, dass wir nicht die letzte Karte codieren müssen, weil wir wissen, was es sein soll. Eine weitere Ersparnis wäre, wenn wir auf einem einzigen Rang enden würden. Wenn zum Beispiel die letzten 3 Karten im Deck 777 , müssten wir diese nicht codieren, da der Decoder die Karten bis zu diesem Punkt zählt und sicherstellt, dass alle anderen Ränge belegt sind und die 3 " annehmen. Fehlende "Karten sind alle 7 s.

Meine Frage an diese Site ist, welche anderen Optimierungen möglich sind, um eine noch kleinere Ausgabedatei für diese Art von Daten zu erhalten, und wenn wir sie verwenden, können wir jemals die theoretische (einfache) Bitpack-Entropie von 3.70044 Bits pro Symbol übertreffen oder Annäherung an die ultimative Entropie-Grenze von durchschnittlich 3.2 Bit pro Symbol? Wenn das so ist, wie?

Wenn ich ein ZIP-Programm verwende (zum Beispiel WinZip), sehe ich nur eine 2:1 Komprimierung, die mir sagt, dass es nur ein "faules" Bitpack mit 4 Bits macht. Wenn ich die Daten mit meinem eigenen Bitpacking "vorkomprimiere", scheint das besser zu sein, denn wenn ich das dann über ein Zip-Programm starte, bekomme ich etwas mehr als 2:1 Komprimierung. Was ich denke ist, warum nicht die ganze Komprimierung selbst machen (weil ich mehr Kenntnisse über die Daten habe als das Zip-Programm). Ich frage mich, ob ich das Entropie-Limit von log ( 13 ) / log ( 2 ) = 3.70044. Ich vermute, ich kann mit den wenigen "Tricks", die ich erwähnte, und ein paar mehr, die ich wahrscheinlich herausfinden kann. Die Ausgabedatei muss natürlich nicht "lesbar" sein. Solange die Kodierung verlustfrei ist, ist sie gültig.

Hier ist ein Link zu 3 Millionen von Menschen lesbaren gemischten Decks ( 1 pro Zeile). Jeder kann an einer kleinen Teilmenge dieser Zeilen "üben" und dann die gesamte Datei rippen lassen. Ich werde weiterhin meine beste (kleinste) Dateigröße basierend auf diesen Daten aktualisieren.

https://drive.google.com/file/d/0BweDAVsuCEM1amhsNmFITnEwd2s/view

Übrigens, falls Sie daran interessiert sind, für welche Art von Kartenspiel diese Daten verwendet werden, finden Sie hier den Link zu meiner aktiven Frage (mit Punkte-Kopfgeld). Mir wurde gesagt, dass es ein (genaues) schweres Problem ist, da es sehr viel Speicherplatz erfordern würde. Einige Simulationen stimmen jedoch mit den ungefähren Wahrscheinlichkeiten überein. Es wurden (noch) keine rein mathematischen Lösungen bereitgestellt. Es ist wohl zu schwer.300

/math/1882705/probability-2-player-card-game-with-multiple-patterns-to-win-who-hat-the-advantage

Ich habe einen guten Algorithmus, der Bits anzeigt, um das erste Deck in meinen Beispieldaten zu codieren. Diese Daten wurden zufällig mit dem Fisher-Yates-Shuffle-Algorithmus generiert. Da es sich um echte Zufallsdaten handelt, scheint mein neu erstellter Algorithmus SEHR gut zu funktionieren, was mich sehr freut.168

In Bezug auf die Komprimierung "Herausforderung", ich bin derzeit bei etwa 160 Bit pro Deck. Ich denke, ich kann vielleicht auf 158 runter gehen. Ja, ich habe es versucht und ich habe 158,43 Bits pro Deck. Ich denke, dass ich mich dem Limit meines Algorithmus nähere, so dass ich es geschafft habe, unter 166 Bit pro Deck zu fallen, aber ich habe keine 156 Bit erhalten, was 3 Bit pro Karte wäre, aber es war eine lustige Übung. Vielleicht werde ich mir in Zukunft etwas überlegen, um jedes Deck im Durchschnitt um 2,43 Bit oder mehr zu reduzieren.


8
Wenn Sie diese gemischten Decks selbst erstellen (anstatt beispielsweise den Status eines physischen Kartenspiels zu beschreiben), müssen Sie das Deck überhaupt nicht speichern - speichern Sie nur den RNG-Startwert, der das Deck erstellt hat.
Jasonharper

3
Ihre Beschreibung und die der Antworten ähneln einem Konzept, das allgemein als Bereichscodierung ( en.wikipedia.org/wiki/Range_encoding ) bezeichnet wird. Sie passen die Wahrscheinlichkeiten nach jeder Karte so an, dass sie die verbleibenden möglichen Karten widerspiegeln.
H. Idden

Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
Gilles 'SO - hör auf böse zu sein'

Antworten:


3

Ein weiterer Punkt, den Sie berücksichtigen sollten: Wenn Sie nur die Komprimierung eines vollständigen Satzes von mehreren Millionen Decks und nicht die Reihenfolge der Decks berücksichtigen möchten, können Sie zusätzliche Flexibilität bei der Codierung erzielen, indem Sie die Informationen zur Reihenfolge der Decks verwerfen . Dies ist beispielsweise der Fall, wenn Sie das Set laden müssen, um alle Decks aufzulisten und zu verarbeiten. Dabei spielt es keine Rolle, in welcher Reihenfolge sie verarbeitet werden.

Sie beginnen damit, jedes Deck einzeln zu codieren, wie in anderen Antworten beschrieben. Sortieren Sie dann diese codierten Werte. Speichern Sie eine Reihe von Unterschieden zwischen den sortierten codierten Werten (wobei der erste Unterschied vom codierten Deck '0' ausgeht). Bei einer großen Anzahl von Decks sind die Unterschiede in der Regel kleiner als der gesamte Codierungsbereich. Sie können also eine Art Varint-Codierung verwenden, um gelegentlich große Unterschiede zu verarbeiten und gleichzeitig die kleineren Unterschiede effizient zu speichern. Das geeignete Sortenschema hängt davon ab, wie viele Decks Sie im Set haben (wodurch die durchschnittliche Differenzgröße bestimmt wird).

Ich kenne die Mathematik leider nicht, inwieweit dies Ihrer Komprimierung helfen würde, dachte aber, dass diese Idee nützlich sein könnte, um darüber nachzudenken.


1
Grob gesagt, wenn Sie mehrere Millionen zufällige Decks haben, betragen die durchschnittlichen Unterschiede ein (mehrere Millionstel) des gesamten Bereichs, was bedeutet, dass Sie ungefähr 20 Bits pro Wert einsparen müssen. Sie verlieren ein wenig für Ihre Varint-Codierung.
Steve Jessop

2
@DavidJames: Wenn die Reihenfolge der Decks nicht wichtig ist, können Sie die 3 Millionen Decks nach der Dekomprimierung neu mischen (dh keine der Decks ändern, ändern Sie einfach die Reihenfolge der Decks) die Liste von 3 Millionen Decks).
Steve Jessop

2
Dies ist nur eine Möglichkeit, den Informationsgehalt weiter zu reduzieren, wenn die Bestellinformationen nicht wichtig sind. Wenn es wichtig ist, ist dies nicht zutreffend und kann ignoriert werden. Das heißt, wenn die einzige Bedeutung für die Reihenfolge der Decks darin besteht, dass sie 'zufällig' ist, können Sie die Reihenfolge nach der Dekomprimierung einfach nach dem Zufallsprinzip sortieren, wie @SteveJessop feststellte.
Dan Bryant

@DavidJames Zu sehen, dass die ersten 173 deiner Decks mit KKKK beginnen und sich nicht die anderen Millionen ansehen, und zu dem Schluss zu kommen, dass alle mit KKKK beginnen, ist eine ziemlich dumme Sache. Besonders wenn sie offensichtlich in einer sortierten Reihenfolge sind.
user253751

3
@DavidJames: Diese Daten werden komprimiert und können bei Bedarf durch die Dekomprimierungsroutine neu randomisiert werden. "Eine naive Person" wird überhaupt nichts bekommen, sie wird nicht einmal herausfinden, wie man es als Kartenstapel interpretiert. Es ist kein Fehler in einem Datenspeicherformat (in diesem Fall ein verlustbehaftetes Format), dass jemand, der es verwendet, RTFM benötigt, um die richtigen Daten herauszubekommen.
Steve Jessop

34

Hier ist ein vollständiger Algorithmus, der die theoretische Grenze erreicht.

Prolog: Codierung ganzzahliger Sequenzen

Eine 13-stellige Folge "Ganzzahl mit Obergrenze , Ganzzahl mit Obergrenze b - 1 ," Ganzzahl mit Obergrenze c - 1 , Ganzzahl mit Obergrenze d - 1 , ... Ganzzahl mit Obergrenze m - 1 " kann immer mit perfekter Effizienz codiert werden.a1b1c1d1m1

  1. Nehmen Sie die erste ganze Zahl, multiplizieren Sie sie mit , addieren Sie die zweite, multiplizieren Sie das Ergebnis mit c , addieren Sie die dritte, multiplizieren Sie das Ergebnis mit d , ... multiplizieren Sie das Ergebnis mit m , addieren Sie die dreizehnte - und das ergibt eine eindeutige Zahl zwischen 0 und a b c d e f g h i j k l m - 1 .bcdm0abcdefghijklm1
  2. Notieren Sie sich diese Zahl in binärer Form.

Das Gegenteil ist auch einfach. Teilen Sie durch und der Rest ist die dreizehnte ganze Zahl. Teilen Sie das Ergebnis durch l und der Rest ist die zwölfte ganze Zahl. Fahren Sie fort, bis Sie durch b geteilt haben : Der Rest ist die zweite Ganzzahl und der Quotient die erste Ganzzahl.mlb

Um Ihre Karten bestmöglich zu codieren, müssen wir lediglich eine perfekte Entsprechung zwischen 13-Integer-Sequenzen (mit vorgegebenen Obergrenzen) und der Anordnung Ihrer gemischten Karten finden.

Hier ist, wie es geht.

Korrespondenz zwischen Shufflings und Integer-Sequenzen

Beginnen Sie mit einer Folge von 0 Karten auf dem Tisch vor Ihnen.

Schritt 1

Nimm die vier 2er in deinen Rucksack und lege sie auf den Tisch.

Welche Möglichkeiten haben Sie? Eine Karte oder Karten können entweder am Anfang der bereits auf dem Tisch befindlichen Sequenz oder nach einer der Karten in dieser Sequenz platziert werden. In diesem Fall bedeutet dies, dass mögliche Plätze zum Ablegen von Karten vorhanden sind.1+0=1

Die Gesamtzahl der Möglichkeiten, 4 Karten an 1 Stellen zu platzieren, ist . Codieren Sie jede dieser Möglichkeiten als Zahl zwischen 0 und 1 - 1 . Es gibt 1 solche Nummer.1011

Ich habe 1 erhalten, indem ich die Schreibweise von 0 als die Summe von 5 ganzen Zahlen betrachte: Es ist .4×3×2×14!

Schritt 2

Nimm die vier 3er in deinen Rucksack und lege sie auf den Tisch.

Welche Möglichkeiten haben Sie? Eine Karte oder Karten können entweder am Anfang der bereits auf dem Tisch befindlichen Sequenz oder nach einer der Karten in dieser Sequenz platziert werden. In diesem Fall bedeutet dies, dass mögliche Plätze zum Ablegen von Karten vorhanden sind.1+4=5

Die Gesamtzahl der Möglichkeiten, 4 Karten an 5 Stellen zu platzieren, beträgt . Encode jede dieser Möglichkeiten als eine Zahl zwischen 0 und 70 - 1 . Es gibt 70 solcher Zahlen.700701

Ich erhielt 70, indem ich die Schreibweise von 4 als die Summe von 5 ganzen Zahlen betrachtete: Es ist .8×7×6×54!

Schritt 3

Nimm die vier 4er in deinen Rucksack und lege sie auf den Tisch.

Welche Möglichkeiten haben Sie? Eine Karte oder Karten können entweder am Anfang der bereits auf dem Tisch befindlichen Sequenz oder nach einer der Karten in dieser Sequenz platziert werden. In diesem Fall bedeutet dies, dass mögliche Plätze zum Ablegen von Karten vorhanden sind.1+8=9

Die Gesamtzahl der Möglichkeiten, 4 Karten an 9 Stellen zu platzieren, beträgt . Encode jede dieser Möglichkeiten als eine Zahl zwischen 0 und 495 - 1 . Es gibt 495 solcher Nummern.49504951

Ich habe 495 erhalten, indem ich die Schreibweise 8 als die Summe von 5 ganzen Zahlen betrachte: Es ist .12×11×10×94!

Und so weiter, bis ...

Schritt 13

Nehmen Sie die vier Asse in Ihren Rucksack und legen Sie sie auf den Tisch.

Welche Möglichkeiten haben Sie? Eine Karte oder Karten können entweder am Anfang der bereits auf dem Tisch befindlichen Sequenz oder nach einer der Karten in dieser Sequenz platziert werden. In diesem Fall bedeutet dies, dass mögliche Plätze zum Ablegen von Karten vorhanden sind.1+48=49

Die Gesamtzahl der Möglichkeiten, 4 Karten an 49 Stellen zu platzieren, beträgt . Encode jede dieser Möglichkeiten als eine Zahl zwischen 0 und 270.725 - 1 . Es gibt 270725 solche Zahlen.27072502707251

Ich erhielt 270725, indem ich die Schreibweise von 48 als die Summe von 5 ganzen Zahlen betrachtete: Es ist .52×51×50×494!


Diese Prozedur ergibt eine 1-zu-1-Entsprechung zwischen (a) Kartenmischungen, bei denen Sie sich nicht für die Farbe interessieren, und (b) Folgen von ganzen Zahlen, bei denen die erste zwischen und 1 - 1 liegt , die zweite zwischen 0 und 70 - 1 , der dritte Wert liegt zwischen 0 und 495 - 1 und so weiter bis zum dreizehnten Wert , der zwischen 0 und 270725 - 1 liegt .01107010495102707251

Unter "Codieren von Ganzzahlfolgen" können Sie erkennen, dass eine solche Folge von Ganzzahlen 1: 1 mit den Zahlen zwischen und ( 1 × 70 × 495 × × 270725 ) - 1 korrespondiert . Wenn Sie sich den Ausdruck "Produkt geteilt durch eine Fakultät" für jede der ganzen Zahlen ansehen ( wie in Kursivschrift am Ende jedes Schritts beschrieben ), werden Sie sehen, dass dies die Zahlen zwischen 0 und 52 bedeutet !0(1×70×495××270725)10was meine vorherige Antwort zeigte, war das bestmögliche.

52!(4!)131,

So haben wir eine perfekte Methode zum Komprimieren Ihrer gemischten Karten.


Der Algorithmus

Berechnen Sie eine Liste aller Schreibweisen von 0 als Summe von 5 Ganzzahlen, von 4 als Summe von 5 Ganzzahlen, von 8 als Summe von 5 Ganzzahlen, von 48 als Summe von 5 Ganzzahlen. Die längste Liste enthält 270725 Elemente, ist also nicht besonders groß. (Eine Vorberechnung ist nicht unbedingt erforderlich, da Sie jede Liste bei Bedarf einfach zusammenstellen können. Mit Microsoft QuickBasic war es sogar schneller, die 270725-Elementliste durchzuarbeiten, als das Auge sehen konnte.)

Um von einem Mischen zu einer Folge von ganzen Zahlen zu gelangen:

Die 2er tragen nichts bei, also ignorieren wir sie. Notieren Sie sich eine Zahl zwischen 0 und 1-1.

Die 3en: Wie viele 2en gibt es vor den ersten 3en? Wie viele vor der zweiten? der dritte? der 4.? nach dem 4.? Die Antwort sind 5 Ganzzahlen, die sich offensichtlich zu 4 addieren. Sehen Sie sich also diese Folge von 5 Ganzzahlen in Ihrer Liste "Schreiben von 4 als Summe von 5 Ganzzahlen" an und notieren Sie sich deren Position in dieser Liste. Das ist eine Zahl zwischen 0 und 70-1. Schreib es auf.

Die 4er: Wie viele 2er oder 3er gibt es vor den ersten 4er? Wie viele vor der zweiten? der dritte? der 4.? nach dem 4.? Die Antwort sind 5 Ganzzahlen, die sich offensichtlich zu 8 addieren. Sehen Sie sich also diese Folge von 5 Ganzzahlen in Ihrer Liste "Schreiben von 8 als Summe von 5 Ganzzahlen" an und notieren Sie sich deren Position in dieser Liste. Das ist eine Zahl zwischen 0 und 495-1. Schreib es auf.

Und so weiter, bis ...

Die Asse: Wie viele Nicht-Ass-Karten gibt es vor dem ersten Ass? Wie viele vor der zweiten? der dritte? der 4.? nach dem 4.? Die Antwort sind 5 Ganzzahlen, die offensichtlich 48 ergeben. Sehen Sie sich also diese Folge von 5 Ganzzahlen in Ihrer Liste "Schreiben von 48 als Summe von 5 Ganzzahlen" an und notieren Sie sich deren Position in dieser Liste. Das ist eine Zahl zwischen 0 und 270725-1. Schreib es auf.

Sie haben jetzt 13 ganze Zahlen aufgeschrieben. Codiere sie (wie zuvor beschrieben) in eine einzelne Zahl zwischen und 52 !0 . Schreiben Sie diese Zahl binär aus. Es wird knapp 166 Bit dauern.52!(4!)13

Dies ist die bestmögliche Komprimierung, da sie die informationstheoretische Grenze erreicht.

Die Dekomprimierung ist unkompliziert: Gehen Sie von der großen Zahl zur Folge von 13 ganzen Zahlen und bauen Sie dann die Kartenfolge wie bereits beschrieben auf.


Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
DW

Diese Lösung ist mir unklar und unvollständig. Es zeigt nicht, wie die 166-Bit-Nummer tatsächlich abgerufen und wieder in das Deck dekodiert werden kann. Es ist überhaupt nicht einfach für mich zu konzipieren, deshalb werde ich nicht wissen, wie ich es implementieren soll. Ihre abgestufte Formel zerlegt im Grunde nur die Formel in 13 Teile, die mir wirklich nicht viel hilft. Ich denke, es hätte geholfen, wenn Sie ein Diagramm oder eine Tabelle für Schritt 2 mit den 70 möglichen Arten der Kartenanordnung erstellt hätten. Ihre Lösung ist zu abstrakt, als dass mein Gehirn sie akzeptieren und verarbeiten könnte. Ich bevorzuge aktuelle Beispiele und Illustrationen. 52!/(4!13)13
David James

23

Anstatt zu versuchen, jede Karte einzeln in 3 oder 4 Bits zu codieren, schlage ich vor, dass Sie den Status des gesamten Decks in 166 Bits codieren. Wie Martin Kochanski erklärt , gibt es weniger als mögliche Anordnungen der Karten, die Farben ignorieren, was bedeutet, dass der Zustand des gesamten Decks in 166 Bits gespeichert werden kann.2166

Wie können Sie diese Komprimierung und Dekomprimierung auf effiziente Weise algorithmisch durchführen? Ich schlage vor, die lexikografische Reihenfolge und die binäre Suche zu verwenden. Auf diese Weise können Sie die Komprimierung und Dekomprimierung effizient durchführen (sowohl räumlich als auch zeitlich), ohne dass eine große Nachschlagetabelle oder andere unrealistische Annahmen erforderlich sind.

Im Einzelnen: Ordnen Sie die Decks anhand der lexikografischen Reihenfolge in der nicht komprimierten Darstellung des Decks, dh ein Deck wird in nicht komprimierter Form als Zeichenfolge wie 22223333444455556666777788889999TTTTJJJJQQQKKKKAAAA dargestellt. Sie können sie in lexikografischer Reihenfolge bestellen. Angenommen, Sie haben eine Prozedur, bei der für ein Deck die Anzahl der Decks gezählt wird, die davor stehen (in lexikografischer Reihenfolge). Mit dieser Prozedur können Sie dann ein Deck komprimieren: Wenn Sie ein Deck D haben , komprimieren Sie es auf eine 166-Bit-Zahl, indem Sie die Anzahl der vorhergehenden Decks zählen und diese Zahl dann ausgeben. Diese Nummer ist die komprimierte Darstellung des Decks.DD

Verwenden Sie zum Dekomprimieren die binäre Suche. Mit einer Nummer möchten Sie das n- te Deck in der lexikografischen Reihenfolge aller Decks finden. Sie können dies mit einer Prozedur nach dem Vorbild der binären Suche tun: Wählen Sie ein Deck D 0 aus , zählen Sie die Anzahl der Decks vor D 0 und vergleichen Sie diese mit n . Hier erfahren Sie, ob Sie D 0 einstellen müssennnD0D0nD0früher oder später kommen. Ich schlage vor, Sie versuchen, iterativ das richtige Symbol zu finden: Wenn Sie eine Zeichenfolge wie 22223333444455556666777788889999TTTTJJJJQQQQKKKKAAAA wiederherstellen möchten, suchen Sie zuerst, was als erstes Symbol in der Zeichenfolge verwendet werden soll (versuchen Sie einfach alle 12 Möglichkeiten oder verwenden Sie die binäre Suche über die 12 Möglichkeiten ). Wenn Sie den richtigen Wert für das erste Symbol gefunden haben, suchen Sie nach dem zweiten Symbol und so weiter.

Alles was bleibt ist, ein effizientes Verfahren zu finden, um die Anzahl der Decks zu zählen, die lexikographisch vor . Dies sieht nach einer einfachen, aber langwierigen kombinatorischen Übung aus. Insbesondere empfehle ich Ihnen, eine Unterroutine für das folgende Problem zu erstellen: Wenn Sie ein Präfix (wie 222234) haben, zählen Sie die Anzahl der Decks, die mit diesem Präfix beginnen. Die Antwort auf dieses Problem scheint eine ziemlich einfache Übung in Binomialkoeffizienten und Fakultäten zu sein. Anschließend können Sie diese Unterroutine einige Male aufrufen, um die Anzahl der Decks vor D zu zählen .DD


Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
DW

8

Die Anzahl der möglichen Anordnungen der Karten , die Farben ignorieren, beträgt dessen Logarithmusbasis 2 165,976 oder 3,1919 Bit pro Karte ist, was besser als das von Ihnen angegebene Limit ist.

52!(4!)13,

Jede feste „Bits pro Karte“ encoding wird nicht sinnvoll , weil, wie Sie beachten, kann die letzte Karte immer in codiert werden Bits und in vielen Fällen sind die letzten paar Karten sein kann als gut. Das bedeutet, dass die Anzahl der Bits, die für jede Karte benötigt werden, auf einem weiten Weg zum "Ende" des Pakets um ein Vielfaches geringer ist, als Sie denken.0

Bei weitem die beste Art, die Daten zu komprimieren, wäre, 59 Bits anderer Daten zu finden, die Sie ohnehin mit Ihren Kartendaten packen möchten (tatsächlich 59,6 Bits) und diese 59 Bits als 13-stelliges Zahlenmodul 24 (= zu schreiben ), Weisen Sie jeder Karte eine Farbe zu (eine Ziffer wählt zwischen den 4 ! Möglichkeiten, den Assen Farben zuzuweisen, eine andere macht dasselbe für die Könige usw.). Dann haben Sie eine Packung mit 52 völlig unterschiedlichen Karten. 52 ! Möglichkeiten können in der Tat sehr leicht in 225,58 Bits codiert werden.4!4!52!

Aber es zu tun, ohne die Gelegenheit zu nutzen, diese zusätzlichen Bits zu codieren, ist in gewissem Maße auch möglich, und ich werde darüber nachdenken, da ich sicher bin, dass es jeder andere ist. Vielen Dank für ein wirklich interessantes Problem!


1
Könnte hier ein Ansatz verwendet werden, der dem Stehlen von Chiffretext ähnelt ? Wie in sind die Daten, die Sie in diesen zusätzlichen 59 Bits codieren, die letzten 59 Bits der codierten Darstellung?
John Dvorak

@JanD Ich habe darüber nachgedacht, so etwas zu untersuchen. Dann stellte sich jedoch heraus, dass es einen Algorithmus gibt, der die theoretische Grenze erreicht und einfach und zu 100% zuverlässig ist. Es hat also keinen Sinn, weiter zu suchen.
Martin Kochanski

@MartinKochanski - Ich würde es nicht als "Anzüge ignorieren" bezeichnen, da wir immer noch die Standard 4 Anzüge pro Rang einhalten. Besserer Wortlaut könnte sein: "Die Anzahl der möglichen unterschiedlichen Anordnungen des Decks ist" ...
David James

3

Dies ist ein lange gelöstes Problem.

Wenn Sie einen Stapel mit 52 Karten austeilen, hat jede Karte, die Sie austeilen, einen von bis zu 13 Rängen mit bekannten Wahrscheinlichkeiten. Die Wahrscheinlichkeiten ändern sich mit jeder Karte. Dies wird unter Verwendung einer alten Technik, der adaptiven arithmetischen Codierung, einer Verbesserung der Huffman-Codierung, optimal gehandhabt. Normalerweise wird dies für bekannte, sich nicht ändernde Wahrscheinlichkeiten verwendet, aber es kann genauso gut zum Ändern von Wahrscheinlichkeiten verwendet werden. Lesen Sie den Wikipedia-Artikel über arithmetische Kodierung:

https://en.wikipedia.org/wiki/Arithmetic_coding


Okay, aber das beantwortet meine Frage nicht, ob es sich der theoretischen Entropie-Kodierungsgrenze annähern, sie angleichen oder sie übertreffen kann. Da es n mögliche Decks mit einer Wahrscheinlichkeit von jeweils 1 / n gibt, ist die Entropiecodierung das Limit und wir können es nicht besser machen (es sei denn, wir "betrügen" und teilen dem Decoder im Voraus etwas über die Eingangsdaten mit.
David James

3

Sowohl DW als auch Martin Kochanski haben bereits Algorithmen zur Konstruktion einer Bijektion zwischen Deals und Integer im Bereich , aber anscheinend hat keiner von ihnen das Problem auf seine einfachste Form reduziert. (Anmerkung 1)[0,52!(4!)13)

Angenommen, wir haben ein (Teil-) Deck, das durch die geordnete Liste , wobei a i die Anzahl der Karten vom Typ i ist . Im OP wird das ursprüngliche Deck durch eine Liste von 13 Elementen beschrieben, von denen jedes den Wert 4 hat. Die Anzahl der unterschiedlichen Mischen eines solchen Decks beträgteineinichich

c(ein)=(einich)!einich!

Dies ist eine einfache Verallgemeinerung der Binomialkoeffizienten, die tatsächlich durch einfaches typweises Anordnen der Objekte bewiesen werden kann, wie von Martin Kochanski vorgeschlagen. (Siehe unten, Anmerkung 2)

Nun können wir für ein solches (Teil-) Deck eine Karte nach der anderen mischen, wobei wir ein beliebiges für das ein i > 0 ist . Die Anzahl der eindeutigen Mischen, die mit i beginnen, isticheinich>0ich

{0ob einich=0c(ein1,...,einich-1,einich-1,einich+1,...,einn)ob einich>0.

und durch die obige Formel haben wir

c(ein1,...,einich-1,einich-1,einich+1,...,einn)=einichc(ein)einich

Wir können dann Rekursion (oder Iterierte) durch das Deck , bis der Shuffle abgeschlossen ist durch die Beobachtung , dass die Anzahl von springt zu einem Präfix entsprechenden lexikographisch kleiner als der Präfix bis istich

c(ein)j=1icheinjj=1neinj

Ich habe dies in Python geschrieben, um den Algorithmus zu veranschaulichen. Python ist ein ebenso vernünftiger Pseudocode wie jeder andere. Beachten Sie, dass der größte Teil der Arithmetik eine erweiterte Genauigkeit beinhaltet. Die Werte (die die Ordnungszahl des Shuffle darstellen) und n (die Gesamtzahl der möglichen Shuffle für den verbleibenden Teilstapel) sind beide 166-Bit-Bignums. Um den Code in eine andere Sprache zu übersetzen, muss eine Art Bignum-Bibliothek verwendet werden.kn

Außerdem verwende ich nur eine Liste von Ganzzahlen anstelle von Kartennamen, und im Gegensatz zu den obigen Berechnungen basieren die Ganzzahlen auf 0.

Um ein Shuffle zu kodieren, gehen wir durch das Shuffle und akkumulieren an jedem Punkt die Anzahl der Shuffles, die mit einer kleineren Karte beginnen, wobei die obige Formel verwendet wird:

from math import factorial
T = factorial(52) // factorial(4) ** 13

def encode(vec):
    a = [4] * 13
    cards = sum(a)
    n = T
    k = 0
    for idx in vec:
        k += sum(a[:idx]) * n // cards
        n = a[idx] * n // cards
        a[idx] -= 1
        cards -= 1
    return k

Das Dekodieren einer 166-Bit-Zahl ist die einfache Umkehrung. Bei jedem Schritt haben wir die Beschreibung eines Teilstapels und einer Ordnungszahl; Wir müssen die Mischvorgänge überspringen, indem wir mit kleineren Karten als der der Ordnungszahl beginnen. Anschließend berechnen wir die Ausgabe der ausgewählten Karte, entfernen sie aus dem verbleibenden Stapel und passen die Anzahl der möglichen Mischvorgänge mit dem ausgewählten Präfix an:

def decode(k):
    vec = []
    a = [4] * 13
    cards = sum(a)
    n = T
    while cards > 0:
        i = cards * k // n
        accum = 0
        for idx in range(len(a)):
            if i < accum + a[idx]:
                k -= accum * n // cards
                n = a[idx] * n // cards
                a[idx] -= 1
                vec.append(idx)
                break
            accum += a[idx]
        cards -= 1
    return vec

Ich habe nicht wirklich versucht, den obigen Code zu optimieren. Ich habe es mit der gesamten 3mil.TXT-Datei verglichen und dabei überprüft, ob encode(decode(line))die ursprüngliche Codierung vorliegt . Es dauerte knapp 300 Sekunden. (Sieben der Zeilen sind im Online-Test von ideone zu sehen .) Das Umschreiben in eine niedrigere Sprache und das Optimieren der Unterteilung (was möglich ist) würden diese Zeit wahrscheinlich auf etwas Verwaltbares verkürzen.

Da der codierte Wert einfach eine Ganzzahl ist, kann er in 166 Bit ausgegeben werden. Das Löschen der führenden Nullen hat keinen Wert, da dann nicht festgestellt werden kann, wo eine Codierung beendet wurde. Es handelt sich also tatsächlich um eine 166-Bit-Codierung.

Es ist jedoch erwähnenswert, dass es in einer praktischen Anwendung wahrscheinlich nie notwendig ist, eine Zufallswiedergabe zu codieren. Eine zufällige Mischung kann erzeugt werden, indem eine zufällige 166-Bit-Zahl erzeugt und dekodiert wird. Und es ist nicht wirklich notwendig, dass alle 166 Bits zufällig sind; Es wäre zum Beispiel möglich, mit einer 32-Bit-Zufallszahl zu beginnen und dann die 166 Bit unter Verwendung eines beliebigen Standard-RNG zu füllen, der mit der 32-Bit-Zahl geimpft ist. Wenn das Ziel einfach darin besteht, eine große Anzahl von Zufallsmischungen reproduzierbar zu speichern, können Sie den Speicherbedarf pro Geschäft mehr oder weniger beliebig reduzieren.

Wenn Sie eine große Anzahl von tatsächlichen Deals codieren möchten (auf andere Weise generiert), sich aber nicht um die Reihenfolge der Deals kümmern möchten , können Sie die sortierte Liste der Nummern deltacodieren, wobei Sie ungefähr 2 N Bits pro Deal speichern Nummer. (Die Einsparungen ergeben sich aus der Tatsache, dass eine sortierte Sequenz weniger Entropie als eine unsortierte Sequenz hat. Sie verringert nicht die Entropie eines einzelnen Werts in der Sequenz.)NLog2N

Unter der Annahme, dass wir eine sortierte Liste von k- Bit-Zahlen codieren müssen, können wir wie folgt vorgehen:N k

  1. Wählen Sie als Ganzzahl in der Nähe von log 2 N (entweder der Boden oder die Decke werden funktionieren; ich gehe normalerweise für die Decke).pLog2N

  2. Wir teilen den Zahlenbereich implizit durch ein binäres Präfix in Intervalle auf. Jedes k -Bit - Zahl wird in einen geteilten p -Bit - Präfix und einem k - p -Bit - Suffix; Wir schreiben nur die Suffixe (in der Reihenfolge). Dies erfordert N ( k - p ) Bits.2pkpk-pN(k-p)

  3. Zusätzlich erstellen wir eine Bitsequenz: Für jedes der Präfixe (außer Präfix 0 ) schreiben wir eine 0 für jede Zahl mit diesem Präfix (falls vorhanden), gefolgt von einer 1 . Diese Sequenz hat offensichtlich 2 p + N Bits: 2 p 1 s und N 0 s.2p0012p+N2p 1N 0

Um die Zahlen zu dekodieren, starten wir einen Präfixzähler bei 0 und arbeiten die Bitsequenz ab. Wenn wir eine , geben wir das aktuelle Präfix und das nächste Suffix aus der Suffixliste aus. Wenn wir eine 1 sehen , erhöhen wir das aktuelle Präfix.01

Die Gesamtlänge der kodierenden ist , die sehr nahe ist N * ( k - p ) + N + N oder N * ( k - p + 2 ) , für einen durchschnittlichen von k - p + 2 Bits pro Wert.N(kp)+N+2pN(kp)+N+NN(kp+2)kp+2

Anmerkungen

  1. ist920242422302710403571083208018720448447500000000undlog252!52!(4!)1392024242230271040357108320801872044844750000000000 ist ungefähr165,9765. In dem Text gehe ich gelegentlich davon aus, dass der Logarithmus zur Basis 2 tatsächlich166 ist. Im Falle der Erzeugung von Zufallsordnungszahlen innerhalb des Bereichs könnte ein Zurückweisungsalgorithmus verwendet werden, der eine erzeugte Zufallszahl nur sehr selten zurückweist.Log252!(4!)13165.9765166
  2. Der Einfachheit halber schreibe ich für n i = k a i ; dann können die a 1 Objekte vom Typ 1 in ( S 1Skich=kneinichein11Wege, und danndie Objekte vom Typ2kann in platziert werden(S2(S1ein1)2Wege und so weiter. Da ( Si(S2ein2), das führt zur Gesamtzählung(Sicheinich)=Sich!einich!(Sich-einich)!=Sich!einich!Sich+1!

ich=1nSich!ich=1neinich!Sich+1!

Dies vereinfacht die obige Formel.


Kommentare sind nicht für eine längere Diskussion gedacht. Diese Unterhaltung wurde in den Chat verschoben .
DW

@rici - Ich gab dir das Kopfgeld von +100, weil du deine Antwort in einer anscheinend besseren Präsentation mit Code erklärt hast, während die anderen Antworten abstrakter / theoretischer sind und einige Details darüber weggelassen hast, wie die Codierung / Decodierung tatsächlich implementiert wird. Wie Sie vielleicht wissen, gibt es beim Schreiben von Code viele Details. Ich gebe zu, mein Algorithmus ist nicht der einfachste, einfachste und verständlichste, aber ich habe ihn tatsächlich ohne großen Aufwand zum Laufen gebracht und kann ihn mit der Zeit mit mehr Komprimierung schneller zum Laufen bringen. Also danke für deine Antwort und mach weiter so.
David James

2

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) .3754EIN236J7131372613762,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 2654EIN236J23456789TJQ.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,9751354EIN236J7

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,1121312122 = 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 ...322223333444455556666777788889999TTTTJJJJQ.Q.Q.Q.KKKKEINEINEINEIN40

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
    54EIN236J  87726Q.3  3969EINEINEIN  Q.JK7T  9292Q.  36K  J57   T8TKJ4  48Q.8T  55K  4
13                                            12                    xy     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).


3
Ich stelle fest, dass Sie innerhalb von 9 Stunden etwa 24 Änderungen vorgenommen haben. Ich schätze Ihren Wunsch, Ihre Antwort zu verbessern. Jedes Mal, wenn Sie die Antwort bearbeiten, wird diese jedoch an den oberen Rand der Startseite verschoben. Aus diesem Grund raten wir von übermäßiger Bearbeitung ab. Wenn Sie damit rechnen, dass Sie viele Änderungen vornehmen, können Sie Ihre Änderungen stapelweise vornehmen, sodass Sie alle paar Stunden nur eine Änderung vornehmen? (Beachten Sie im Übrigen, dass das Einfügen von "EDIT:" und "UPDATE:" in Ihre Antwort normalerweise einen schlechten Stil hat. Siehe meta.cs.stackexchange.com/q/657/755. )
DW

4
Hier können keine Fortschrittsberichte, Statusaktualisierungen oder Blogeinträge abgelegt werden. Wir wollen fundierte Antworten, nicht "in Kürze" oder "Ich habe eine Lösung, aber ich werde nicht beschreiben, was es ist".
DW

3
Wenn jemand interessiert ist, wird er die verbesserte Lösung finden. Der beste Weg ist, auf die vollständige Antwort zu warten und sie dann zu posten. Wenn Sie einige Updates haben, würde ein Blog tun. Ich ermutige dies nicht, aber wenn Sie wirklich (ich sehe keinen gültigen Grund warum) müssen, können Sie einen Kommentar unter Ihren Beitrag schreiben und später zusammenführen. Ich empfehle Ihnen auch, alle veralteten Kommentare zu löschen und sie in eine nahtlose Frage zu integrieren - es wird schwierig, alle zu lesen. Ich versuche, meinen eigenen Algorithmus zu erstellen, der sich von den vorgestellten Algorithmen unterscheidet, aber ich bin nicht zufrieden mit den Ergebnissen - daher poste ich keine zu bearbeitenden Partials - das Antwortfeld ist für vollständige.
Evil

3
@ DavidJames, ich verstehe. Dies ändert jedoch nichts an unseren Richtlinien: Nehmen Sie nicht so viele Änderungen vor. (Wenn Sie Verbesserungen für die Website vorschlagen möchten , können Sie einen Beitrag auf unserer Meta für Informatik oder auf meta.stackexchange.com veröffentlichen, der dies vorschlägt. Entwickler lesen diesen Kommentarthread nicht.) Aber in der Zwischenzeit haben wir Arbeiten Sie mit der Software, die wir haben, und es wird davon abgeraten, viele Änderungen vorzunehmen, da hierdurch die Frage nach oben gerückt wird. An dieser Stelle ist es möglicherweise eine gute Richtlinie, sich auf eine Bearbeitung pro Tag zu beschränken. Fühlen Sie sich frei, Offline-Editoren oder StackEdit zu verwenden, wenn das hilft!
DW

3
Ich stimme Ihrer Antwort aus mehreren Gründen nicht zu. 1) es ist unnötig lang und viel zu ausführlich. Sie können die Darstellung drastisch reduzieren. 2) Es gibt bessere Antworten, die Sie aus mir unbekannten Gründen ignorieren. 3) Fragen über fehlende Upvotes sind für mich normalerweise eine "rote Fahne". 4) Dies ist aufgrund einer FANTASTISCHEN Anzahl von Bearbeitungen ständig auf der Titelseite geblieben.
Nicholas Mancuso
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.