Ich möchte positive ganze Zahlen kompakt x
in Bits codieren , so dass ein zustandsloser Decoder, der den Maximalwert m
von jedem kennt, wieder in die ursprünglichen ganzen Zahlen decodieren kann x
. Es soll möglich sein, die Verkettung von Codierungen eindeutig zu decodieren, wie dies bei der Huffman-Codierung der Fall ist.
[Die obige Einleitung motiviert den Rest, ist aber nicht Teil der formalen Definition]
Notation: Für jede nicht negative ganze Zahl i
sei n(i)
die Anzahl der Bits, die zur Darstellung i
in Binärzahlen erforderlich sind . das ist die kleinste nicht negative ganze Zahl, k
so dassi>>k == 0
i : 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 ..
n(i): 0 1 2 2 3 3 3 3 4 4 4 4 4 4 4 4 5 5 5 ..
Ich möchte eine Funktion, F(x,m)
die für 0<x
und x<=m
mit der Ausgabe einer Zeichenfolge von ' 0
' oder ' 1
' definiert ist und folgende Eigenschaften aufweist:
F(x,m)
hat eine Länge von weniger als2*n(x)
oder2*n(m)-1
, je nachdem, welcher Wert kleiner ist.- Wenn
x<y
dann:F(x,m)
ist nicht länger alsF(y,m)
;F(x,m)
undF(y,m)
unterscheiden sich an einer Position über die Länge vonF(x,m)
;- Es gibt ein
0
InF(x,m)
an der ersten solchen Position.
- Wenn für bestimmte
m
Eigenschaften 1 und 2 höchstens nichtF(x,m)
für alle positiven Eigenschaften eindeutig definiert sind , lehnen wir jede Codierung ab, die eine längere als eine ansonsten akzeptable Codierung ergibt , für die kleinste, für die die Länge nicht übereinstimmt.x
m
F(x,m)
x
Hinweis: Bei der oben implizit 0<x
, 0<y
, 0<m
, x<=m
, und y<=m
, so dass F(x,m)
und F(y,m)
definiert.
Es ist das kürzeste Programm darum gebeten , dass, da jeder x
und die m
Erfüllung die oben genannten Einschränkungen und bis zu 9 Dezimalstellen, gibt eine in F(x,m)
Übereinstimmung mit den oben genannten Regeln. Das folgende C-Framework (oder sein Äquivalent in anderen Sprachen) wird nicht gezählt:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C(c) putchar((c)?'1':'0') // output '0' or '1'
#define S(s) fputs((s),stdout) // output a string
typedef unsigned long t; // at least 32 bits
void F(t x,t m); // prototype for F
int main(int argc,char *argv[]){
if(argc==3)F((t)atol(argv[1]),(t)atol(argv[2]));
return 0;}
void F(t x,t m) { // counting starts on next line
} // counting ends before this line
Kommentar: Eigenschaft 1 begrenzt die codierte Länge aggressiv. Eigenschaft 2 formalisiert, dass eine eindeutige Decodierung möglich ist, und kanonisiert die Codierung; Ich behaupte (ohne Beweis), dass dies ausreicht, um die Ausgabe von F
wann m+1
eine Zweierpotenz eindeutig zu definieren, und dass Eigenschaft 3 ausreicht, um F
für andere eindeutig zu definieren m
.
Hier ist eine Teiltabelle (handgemacht; die erste veröffentlichte Version war voller Fehler, sorry):
x : 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
F(x,1) : empty
F(x,2) : 0 1
F(x,3) : 0 10 11
F(x,4) : 0 10 110 111
F(x,5) : 0 10 110 1110 1111
F(x,6) : 0 100 101 110 1110 1111
F(x,7) : 0 100 101 1100 1101 1110 1111
F(x,8) : 0 100 101 110 11100 11101 11110 11111
F(x,15) : 0 100 101 11000 11001 11010 11011 111000 111001 111010 111011 111100 111101 111110 111111
11111
, die Dekodierung unmöglich machen. Mit der vorgeschlagenen Codierung kann die Verkettung mehrerer Ausgänge eindeutig decodiert werden (auch wenn sich das Maximumm
dynamisch ändert). Ich habe versucht, das zu klären.Antworten:
Python 3, 163 Bytes
Ignoriere den
c=0
Parameter, das ist ein Golftrick.Dies wählt gierig die kürzestmögliche Darstellung für jede Zahl, unter der Bedingung, dass die verbleibenden Zahlen noch darstellbar sind. Daher erfüllt es konstruktionsbedingt genau die gewünschten Eigenschaften. Es ist tatsächlich nicht so schwer, diesen Code zu ändern, um einen anderen Satz von Codierungsregeln zu unterstützen.
Hier sind zum Beispiel die Ausgaben bis zu
m=15
:quelle
Python, 171
Beachten Sie, dass Zeilen, die mit 4 Leerzeichen zu beginnen scheinen, tatsächlich mit einer Registerkarte beginnen.
Testen mit dem Bitpwner-Testskript:
Erläuterung:
Dies alles basiert auf der Beobachtung, dass wir zwischen zwei aufeinanderfolgenden Elementen des Codes, F (x, m) und F (x + 1, m), immer eins zur Binärzahl addieren und dann einige Male mit zwei multiplizieren. Wenn diese Schritte ausgeführt werden, handelt es sich um einen gültigen Code. Der Rest testet einfach, um sicherzustellen, dass es kurz genug ist.
Golf: 175 -> 171: geändert 2 ** (2 * ... auf 4 **)
quelle
Python - 370
Erstellt einen Huffman-Baum, gleicht ihn gemäß den Regeln aus und geht dann durch den Baum, um die endgültigen Werte zu erhalten.
Eine prägnantere Lösung, die auf dem entstehenden Muster basiert, finden Sie in der Antwort von isaacg.
Es ist ein gutes Beispiel dafür, wie ein völlig anderer Ansatz das Problem lösen kann.
Prüfung:
Ergebnisse:
quelle
F(7,8)
of111110
falsch, denn das hat die Länge 6 und "weniger als2*n(x)
" impliziert weniger als 6.