Come soluzione alternativa a questo problema, il mio algoritmo utilizza bit frazionari composti (non interi) per carta per gruppi di carte nel mazzo in base al numero di ranghi rimasti vuoti. È un algoritmo piuttosto elegante. Ho controllato manualmente il mio algoritmo di codifica e sta andando bene. L'encoder sta emettendo quelle che sembrano essere stringhe di bit corrette (in forma di byte per semplicità).
La panoramica del mio algoritmo è che utilizza una combinazione di gruppi di carte e codifica di bit frazionata composta. Ad esempio, nel mio file di prova condiviso di milioni di mazzi mescolate, il primo ha le prime 7 carte di 54 A 236 J . Il motivo per cui ho scelto una dimensione di blocco di 7 carte quando sono possibili 13 gradi di carte è perché 13 7 "calzascarpe" (si adatta comodamente) in 26 bit (poiché 13 7 = 62 , 748 , 517 e 2 26 = 67 , 108 ,3754A 236 J7131372613762 , 748 , 517226 ). Idealmente, vogliamo che quei 2 numeri siano il più vicino possibile (ma con la potenza di 2 numeri leggermente superiore), quindi non perdiamo più di una piccolissima frazione di bit nel processo di imballaggio dei bit. Nota: avrei potuto anche scegliere la dimensione di gruppo 4 durante la codifica di 13 gradi poiché 13 4 = 28 , 561 e 2 15 = 32 , 768 . Non è stretto una misura dal 15 / 4 = 3.75 ma 26 / 7 = 3.71467 , 108 , 864241313428 , 56121532 , 76815 / 4 = 3.7526 / 7 = 3.714. Così il numero di bit per carta è leggermente inferiore per ogni carta, se usiamo il metodo di imballaggio.26 / 7
Quindi, guardando , osserviamo semplicemente la posizione ordinale di quei ranghi nella nostra lista principale di ranghi ordinati " 23456789 T J Q K A ". Ad esempio, il primo rango di carta effettivo di 5 ha una posizione di ricerca nella stringa di ricerca di rango di 4 . Trattiamo queste 7 posizioni di rango come un numero di base 13 che inizia con 0 (quindi la posizione 4 che abbiamo ottenuto in precedenza sarà effettivamente un 3). Convertito alla base 10 (a scopo di controllo), otteniamo 15 , 565 , 975 . Nel 2654 A236 J23456789 TJQ KUN547131015 , 565 , 97526bit di binario otteniamo .00111011011000010010010111
Il decodificatore funziona in modo molto simile. Prende (ad esempio) quella stringa di bit e la converte in decimale (base 10) per ottenere 15 , 565 , 975 , quindi la converte in base 13 per ottenere gli offset nella stringa di ricerca dei ranghi, quindi ricostruisce i ranghi uno alla volta e ottiene le prime 7 carte 54 A 236 J originali . Notare che la dimensione dei blocchi non sarà sempre 26 ma inizierà sempre a 26 in ciascun mazzo. L'encoder e il decoder hanno entrambi alcune informazioni importanti sui dati del deck anche prima che funzionino. Questa è una cosa eccezionalmente bella di questo algoritmo.2615 , 565 , 9751354 A 236 J7
Ogni ° ranghi rimanente (ad esempio ha una propria groupsize e il costo (# di bit per carta). Questi sono stati trovati sperimentalmente solo giocando con poteri di 13 , 12 , 11 ... e poteri di 2 . Ho già spiegato come ho ottenuto la dimensione del gruppo per quando possiamo vedere 13 gradi, quindi che ne dite quando scendiamo a 12 gradi non riempiti? Stesso metodo Guarda i poteri di 12 e fermati quando uno di loro si avvicina molto a un potere di 2 ma appena leggermente sotto di esso. 13 , 12 , 11 . . . , 2 , 1 )13 , 12 , 11 ...21312122 = 248 , 832 e 2 18 = 262 , 144 . Questa è una misura abbastanza stretta. Il numero di bit che codificano questo gruppo è 18 / 5 = 3,6 . Nel 13 gruppo rango era 26 / 7 = 3.714 così come si può vedere, il numero di ranghi vacanti diminuisce (ranghi sono riempiendo come 5555 , 3333 ), il numero di bit per codificare le carte diminuisce.125248 , 832218262 , 14418 / 53.61326 / 73.71455553333
Ecco il mio elenco completo dei costi (n. Di bit per scheda) per tutti i possibili n. Di ranghi da visualizzare:
= 3.000 = 3 7 17 / 6 = 2.833 = 213 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
1 0 / 1..4 = 0.0 = 0 2 1 / 1 = 1.000 = 1
1 0 / 1..4 = 0.0 = 0
Come puoi vedere chiaramente, quando il numero di ranghi vuoti diminuisce (cosa che farà ogni mazzo), diminuisce anche il numero di bit necessari per codificare ogni carta. Potresti chiederti cosa succede se riempiamo un grado ma non abbiamo ancora un gruppo. Ad esempio, se le prime carte nel mazzo fossero 5 , 6 , 7 , 7 , 7 , 7 , K , cosa dovremmo fare? Facile, il K normalmente lascerebbe cadere l'encoder dalla modalità di codifica a 13 gradi alla modalità di codifica a 12 gradi. Tuttavia, poiché non abbiamo ancora riempito il primo blocco di 7 carte in 1375 , 6 , 7 , 7 , 7 , 7 , KK1312713classifica la modalità di codifica, includiamo la in quel blocco per completarla. Ci sono pochissimi rifiuti in questo modo. Ci sono anche casi mentre stiamo cercando di riempire un blocco, il numero di ranghi riempiti aumenta di 2 o anche di più. Anche questo non è un problema poiché riempiamo il blocco nella modalità di codifica corrente, quindi riprendiamo nella nuova modalità di codifica che può essere 1 , 2 , 3 ... in meno o addirittura rimanere nella stessa modalità (come nel caso nel primo mazzo nel file di dati in quanto vi sono 3 blocchi completi nella modalità di codifica di 13 gradi). Questo è il motivo per cui è importante rendere ragionevoli le dimensioni dei blocchi, ad esempio tra le dimensioni 1 e 7K21 , 2 , 3 ...31317. Se lo rendessimo di dimensioni ad esempio, dovremmo riempire quel blocco con un bitrate più alto rispetto a se lasciamo che il codificatore passi a una modalità di codifica più efficiente (codificando meno ranghi).20
Quando ho eseguito questo algoritmo (a mano) sul primo mazzo di carte nel file di dati (che è stato creato usando shuffle imparziale Fisher-Yates), ho ottenuto un impressionante bit da codificare che è quasi identico alla codifica binaria ottimale ma non richiede conoscenza delle posizioni ordinali di tutti i mazzi possibili, nessun numero molto grande e nessuna ricerca binaria. Richiede tuttavia manipolazioni binarie e anche manipolazioni radix (potenze di 13 , 12 , 11 ...).16813 , 12 , 11
10777748747S. Se il mazzo termina su una coppia (come 77), triplo / set (come 777) o un quad (come 7777), otteniamo ulteriori risparmi per quel mazzo usando il mio algoritmo.
3222613163232
Nel primo mazzo nel file di dati, la codifica delle carte è la seguente (diagramma che verrà dopo). Il formato è (groupize, bit, modalità codifica rango):
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,7K8101carta rimanente. Questo è importante perché rende il processo di codifica più efficiente quando il decodificatore può fare ipotesi corrette senza che l'encoder debba passare messaggi extra ad esso.
313121110
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. Nota che alla fine del mazzo abbiamo ottenuto solo un 4, ma se invece avessimo lì tutti e quattro i 4, questo è un caso migliore e avremmo avuto bisogno solo di 161 bit per codificare quel mazzo, un caso in cui l'imballaggio batte effettivamente il entropia di una codifica binaria diritta della sua posizione ordinale.
Ora ho implementato il codice per calcolare i requisiti di bit e mi mostra in media, circa 175 bit per deck con un minimo di 155 e un massimo di 183 per il file di test di 3 milioni di deck. Quindi il mio algoritmo sembra usare 9 bit extra per deck rispetto alla codifica binaria diritta del metodo della posizione ordinale. Non male, è richiesto solo il 5,5% di spazio di archiviazione aggiuntivo. 176 bit sono esattamente 22 byte, quindi è un po 'meglio di 52 byte per deck. Il mazzo del caso migliore (non mostrato in 3 milioni di file di test del mazzo) è composto da 136 bit e il mazzo del caso peggiore (mostrato nel file di test 8206 volte), è 183 bit. L'analisi mostra che il caso peggiore è quando non otteniamo il primo quadrupolo fino a quando vicino alla (o alla) carta 40. Quindi, poiché la modalità di codifica vuole cadere rapidamente, siamo "bloccati" riempiendo blocchi (grandi quanto 7 carte) in un modalità di codifica bit superiore. Si potrebbe pensare che non ottenere alcun quadruplo fino a quando la carta 40 non sarebbe abbastanza rara usando un mazzo ben mischiato, ma il mio programma mi sta dicendo che è successo 321 volte nel file di test di 3 milioni di mazzi in modo da farlo circa 1 su ogni 9346 mazzi. Questo è più spesso che mi sarei aspettato. Potrei verificare questo caso e gestirlo con meno bit ma è così raro che non influirebbe abbastanza sui bit medi.
Anche qui c'è qualcos'altro di molto interessante. Se ordino il mazzo in base ai dati grezzi del mazzo, la lunghezza dei prefissi che ripetono un numero significativo di volte è solo circa la lunghezza 6 (come 222244). Tuttavia, con i dati compressi, tale lunghezza aumenta a circa 16. Ciò significa che se ordino i dati compressi, dovrei essere in grado di ottenere un risparmio significativo semplicemente indicando al decodificatore un prefisso a 16 bit e quindi emettere il resto dei deck (meno il prefisso ripetuto) che hanno lo stesso prefisso, quindi vai al prefisso successivo e ripeti. Supponendo di salvare anche solo 10 bit per deck in questo modo, dovrei battere i 166 bit per deck. Con la tecnica di enumerazione dichiarata da altri, non sono sicuro che il prefisso sarebbe lungo quanto il mio algoritmo. Anche la velocità di imballaggio e decompressione usando il mio algoritmo è sorprendentemente buona.
Per quanto riguarda il 2 ° livello di compressione in cui ordino le stringhe di output del mio algoritmo, quindi uso la codifica "differenza": un metodo molto semplice sarebbe codificare i 61.278 prefissi univoci a 16 bit che compaiono almeno due volte nei dati di output (e un massimo di 89 volte riportate) semplicemente come bit iniziale di 0 nell'output per indicare al decompressore di 2 ° livello che stiamo codificando un prefisso (come 0000111100001111) e quindi qualsiasi mazzo impacchettato con lo stesso prefisso seguirà con un 1 bit iniziale a indica la parte non prefissa del mazzo impaccato. Il numero medio di mazzi impaccati con lo stesso prefisso è di circa 49 per ciascun prefisso, esclusi i pochi che sono univoci (solo 1 mazzo ha quel particolare prefisso). Sembra che posso salvare circa 15 bit per mazzo usando questa semplice strategia (memorizzando i prefissi comuni una volta).
Dopo il 2 ° livello di compressione usando la codifica della differenza (prefisso) dell'uscita bittring ordinata del primo encoder, ora sto ottenendo circa 160 bit per deck. Uso il prefisso lunghezza 18 e lo conservo intatto. Poiché quasi tutti (245013 su 262144 = 93,5%) di quei possibili prefissi a 18 bit vengono visualizzati, sarebbe ancora meglio codificare i prefissi. Forse posso usare 2 bit per codificare il tipo di dati che ho. 00 = prefisso 18 di lunghezza normale memorizzato, 01 = "1 prefisso in alto" (uguale al prefisso precedente tranne 1 aggiunto), 11 = codifica diritta dall'imballaggio di 1 ° livello (circa 175 bit in media). 10 = espansione futura quando penso a qualcos'altro da codificare che salverà i bit.
Qualcun altro ha già battuto 160 bit per mazzo? Penso di poter ottenere il mio un po 'più in basso con alcuni esperimenti e l'uso dei descrittori a 2 bit che ho menzionato sopra. Forse andrà a fondo a 158ish. Il mio obiettivo è di portarlo a 156 bit (o meglio) perché sarebbe 3 bit per scheda o meno. Molto impressionante. Molti esperimenti per arrivare a quel livello perché se cambio la codifica di primo livello, devo ripetere il test quale è la migliore codifica di secondo livello e ci sono molte combinazioni da provare. Alcune modifiche apportate potrebbero essere utili per altri dati casuali simili, ma alcuni potrebbero essere distorti verso questo set di dati. Non ne sono sicuro, ma se ho la voglia di provare un altro set di dati da 3 milioni di deck per vedere cosa succede se ottengo risultati simili.
1050
Qualcuno ha qualche idea su come rendere il mio algoritmo migliore come gli altri casi che dovrei codificare che ridurrebbe in media i bit di archiviazione per ciascun deck? Chiunque?
Altre 2 cose: 1) Sono un po 'deluso dal fatto che più persone non abbiano votato a favore della mia soluzione che, sebbene non sia ottimale nello spazio, è comunque decente e abbastanza facile da implementare (ho fatto funzionare bene la mia). 2) Ho fatto un'analisi sul mio file di dati di 3 milioni di deck e ho notato che la carta che si verifica più frequentemente in cui si riempie il 1 ° grado (come 4444) si trova sulla carta 26. Ciò accade circa il 6,711% del tempo (per 201322 dei 3 milioni di mazzi ). Speravo di usare queste informazioni per comprimere di più come iniziare nella modalità di codifica a 12 simboli poiché sappiamo in media che non vedremo tutti i ranghi fino a circa il medio, ma questo metodo non è riuscito a comprimere poiché il sovraccarico ha superato i risparmi. Sto cercando alcune modifiche al mio algoritmo che possono effettivamente salvare bit.
Qualcuno ha qualche idea di cosa dovrei provare dopo per salvare qualche bit per mazzo usando il mio algoritmo? Sto cercando un modello che si verifichi abbastanza frequentemente in modo da poter ridurre i bit per deck anche dopo il sovraccarico aggiuntivo di dire al decoder quale modello aspettarsi. Stavo pensando a qualcosa con le probabilità attese delle rimanenti carte invisibili e raggruppando tutte le singole carte rimanenti in un singolo secchio. Questo mi permetterà di passare a una modalità di codifica inferiore più velocemente e forse di salvare alcuni bit, ma ne dubito.
Inoltre, FYI, ho generato 10 milioni di riordini casuali e li ho archiviati in un database per una facile analisi. Solo 488 di loro finiscono in un quad (come 5555). Se comprimo solo quelli che usano il mio algoritmo, ottengo in media 165.71712 bit con un minimo di 157 bit e un alto di 173 bit. Appena leggermente al di sotto dei 166 bit usando l'altro metodo di codifica. Sono un po 'sorpreso da quanto sia raro questo caso (circa 1 su 20.492 shuffles in media).