Sonst wird er schnauben und pusten und dein Haus in die Luft jagen!
Das war völlig irrelevant. Bei dieser Herausforderung geht es eigentlich um Huffman-Codierung . Das Wesentliche ist, dass die Häufigkeit der Zeichen in einem bestimmten Text verwendet wird, um seine Darstellung zu verkürzen. Mit anderen Worten, lassen Sie uns sagen, dass unser Alphabet a
durch z
und Raum ist. Das sind 27 Zeichen. Jedes von ihnen kann in nur 5 Bits eindeutig codiert werden, da 5 Bits genug Platz für 32 Zeichen haben. In vielen Situationen (z. B. Englisch oder Sprachen im Allgemeinen) sind einige Zeichen jedoch häufiger als andere. Wir können weniger Bits für die häufigeren Zeichen und (vielleicht) mehr Bits für die weniger häufigen Zeichen verwenden. Richtig gemacht, ergibt sich eine Gesamtersparnis bei der Anzahl der Bits, und der ursprüngliche Text kann immer noch eindeutig rekonstruiert werden.
Nehmen wir als Beispiel "Diese Frage handelt von Huffman-Codierung". Dieser Text ist 37 Zeichen lang, was normalerweise 37 * 8 = 296 Bit wäre, obwohl nur 37 * 5 = 185 Bit, wenn wir nur 5 Bit für jedes Zeichen verwenden. Merk dir das.
Hier ist eine (sorta) Tabelle der einzelnen Zeichen und ihrer Häufigkeiten im Text, sortiert von am häufigsten bis am seltensten (wobei _ für ein Leerzeichen steht):
_ 5
i 4
n 3
o 3
s 3
t 3
u 3
a 2
f 2
h 2
b 1
c 1
d 1
e 1
g 1
m 1
q 1
Eine damit verbundene optimale Kodierung könnte sein:
_ 101
i 011
n 1100
o 1101
s 1110
t 1111
u 001
a 10011
f 0001
h 0101
b 00000
c 00001
d 01000
e 01001
g 10000
m 10001
q 10010
Es sollte sofort klar sein, dass dies eine bessere Codierung ist, als nur 5 Bits für jedes Zeichen zu verwenden. Lassen Sie uns herausfinden, wie viel besser!
145 Bits , verglichen mit 185! Das ist eine Ersparnis von 40 Bit oder etwas mehr als 20%! (Dies setzt natürlich voraus, dass Informationen über die Struktur zum Decodieren verfügbar sind.) Diese Codierung ist optimal, da durch Ändern der Zeichendarstellung keine Bits mehr gelöscht werden können.
Die Aufgabe
- Schreiben Sie ein Programm oder eine Funktion mit einem Parameter, der ...
- Übernimmt die Eingabe von STDIN (oder einer Entsprechung) oder als einzelnes Argument.
- Geben Sie eine optimale Huffman-Codierung wie oben mit den nach Häufigkeit sortierten Zeichen aus (die Reihenfolge innerhalb einer Häufigkeit spielt keine Rolle).
- Sie können davon ausgehen, dass die Zeichen in der Eingabe auf den ASCII-Bereich
32..126
plus eine neue Zeile beschränkt sind. - Sie können davon ausgehen, dass die Eingabe nicht länger als 10.000 Zeichen ist (im Idealfall sollte die Eingabe theoretisch unbegrenzt sein).
- Ihr Code sollte ziemlich schnell fertig sein. Das obige Beispiel sollte im schlimmsten Fall nicht länger als eine Minute dauern. (Dies soll brachiale Gewalt ausschließen.)
- Die Bewertung erfolgt in Byte.
Beispiele
x
---
x 0
xxxxxxxxx
---
x 0
xxxxxxxxy
---
x 0
y 1 (these may be swapped)
xxxxxyyyz
---
x 0
y 10
z 11
uuvvwwxxyyzz
--- (or)
u 000 000
v 001 001
w 100 010
x 101 011
y 01 10
z 11 11
this question is about huffman coding
---
101
i 011
n 1100
o 1101
s 1110
t 1111
u 001
a 10011
f 0001
h 0101
b 00000
c 00001
d 01000
e 01001
g 10000
m 10001
q 10010
Viel Spaß beim Codieren!
Beachten Sie, dass diese ähnliche Frage eng verwandt ist, auch wenn es sich um ein Duplikat handelt. Doch der Konsens bisher ist auf Meta , dass die ältere sollte ein Duplikat dieser eine in Betracht gezogen werden.
quelle
this question is about huffman coding
ich die Anzahl der Bits mit 145 und nicht mit 136 gezählt.Antworten:
Pyth, 53 Bytes
Demonstration
Hier ist eine Version, die den internen Status anzeigt, sodass Sie sehen können, wie die Codierung erstellt wird:
Demonstration
Kopieren Sie die Ausgabe in eine Umgebung mit breiteren Linien, um ein klareres Bild zu erhalten.
quelle
Python 2, 299 Bytes
Hier ist mein Versuch einer Antwort.
Die Huffman-Codes unterscheiden sich von den angegebenen Beispielen, sollten aber immer noch optimal sein.
quelle
Matlab, 116 Bytes
tabulate
macht eine Häufigkeitstabelle.huffmandict
Nimmt eine Liste von Symbolen und Wahrscheinlichkeiten für jedes Symbol und berechnet den Code.quelle
Rubin,
189180 BytesIn Arbeit.
Es ist eine anonyme Funktion. Weisen Sie es zum Beispiel etwas zu
f
und rufen Sie es mit aufDas gibt einen Hash wie diesen zurück:
quelle
Haskell, 227 Bytes
Anwendungsbeispiel:
Wie es funktioniert:
p
Aufrufe,f
die die Huffman-Tabelle in Form einer Liste von (Zeichen-, Codierungs-) Paaren erstellen, z. B.[ ('a',"0"), ('b',"1") ]
die Tabelle nach der Länge der Codierungen sortieren, jedes Paar für die Ausgabe formatieren und mit dazwischen liegenden Zeilenumbrüchen verbinden.f
prüft zunächst die Groß- und Kleinschreibung und gibt die entsprechende Tabelle zurück. Sonst ist es die Eingabezeichenfolge und Gruppen - Sequenzen von gleichen Zeichen sortiert (zB"ababa"
->["aaa","bb"]
) und ordnet sie paarweise(sequence , [(char, "")])
, (->[ ("aaa", [('a',"")]), ("bb", [('b', "")])]
. Das erste Element wird verwendet, Spur der Frequenz zu halten, ist das zweite Element eine Liste von Paaren eines Zeichen und es wird kodiert , (das anfänglich leer ist ). Diese sind alle Einzelelement - Huffman - Tabellen , wie erwartet durchp
und werden kombiniert durchg
undh
.g
sortiert die Liste der Paare nach der Länge des ersten Elements, dh nach der Häufigkeit und den Anrufenh
.h
kombiniert die Huffman-Tabellen der ersten beiden Elemente, indem die Frequenzen verkettet werden und ein0
(1
) vor jedes Element der ersten (zweiten) Tabelle gesetzt wird. Verketten Sie beide Tabellen. Rufen Sieg
erneut an, hören Sie auf, wenn ein einzelnes Element übrig ist, werfen Sie den Frequenzteil weg und geben Sie die vollständige Huffman-Tabelle zurück.quelle
K (ngn / k) , 78 Bytes
Probieren Sie es online!
Gibt eine Liste der zu druckenden Zeichenfolgen zurück
h::0#'x
Erstellt eine leere Liste für jedes Zeichen (technisch gesehen wird jedes Zeichen in Länge 0 geändert). Wir werden die umgekehrten Huffman-Codes dort speichern. Wir verwenden::
statt:
für die Zuweisung, umh
global zu machen, damit es in Unterfunktionen sichtbar ist..=x
ist eine Liste von Listen - die Indizes der Zeichenfolge, gruppiert nach Zeichenwert(#1_)
ist eine Funktion, die true zurückgibt, wenn die Länge des Arguments> 1 ist (technisch gesehen "Länge von 1 Tropfen ...")(#1_){
...}/
bedeutet: Während das Argument eine Länge> 1 hat, wenden Sie weiterhin die geschweifte Klammer anx@<#'x
Sortieren Sie das Argument nach Länge0 2_
Schneiden Sie es in einen 2-Element-Kopf und einen Schwanz{h[x],:!2;y,,,/x}
Aktualisierungh
durch Anhängen von 0 und 1 an die im Kopf enthaltenen Indizes; Geben Sie den Schwanz mit dem Kopf als einzelnes Element zurück(?,/'x,'" ",'|'$h)(?x)?>#'=x
kehren Sie jedesh
Zeichen um, sortieren Sie es, stellen Sie es eindeutig dar, stellen Sie entsprechende Zeichen voran und formatieren Sie es gutquelle
JavaScript (ES6) 279
Im Wesentlichen der grundlegende Algorithmus von Wikipedia. Ich kann es wahrscheinlich besser machen.
Weiter unten im Snippet besser lesbar
quelle