Es ist möglich, einige Arten von Daten, wie z. B. menschlichen Text oder Quellcode, mit geradlinigen Grammatiken zu komprimieren. Sie erstellen im Grunde eine Grammatik, deren Sprache genau ein Wort enthält - die unkomprimierten Daten. In dieser Aufgabe müssen Sie ein Programm schreiben, das diese Methode der Datenverdichtung implementiert.
Eingang
Die Eingabe ist eine Zeichenfolge mit einer Länge von nicht mehr als 65535 Byte. Es wird garantiert, dass die Eingabe mit dem regulären Ausdruck übereinstimmt [!-~]+
(dh mindestens ein druckbares ASCII-Zeichen ohne Leerzeichen).
Eine Beispieleingabe ist
abcabcbcbcabcacacabcabab
Ausgabe
Die Ausgabe besteht aus einer Reihe von Regeln, die eine Grammatik bilden, die genau ein Wort (die Eingabe) beschreibt. Jedes Nichtterminal wird durch eine Dezimalzahl größer als 9 gekennzeichnet. Das Startsymbol ist die Symbolnummer zehn. Eine Beispielausgabe, die der Beispieleingabe entspricht, ist unten angegeben; Die Syntax wird weiter unten beschrieben:
10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b
Jede Regel hat die Form <nonterminal>=<symbol> <symbol> ...
mit einer beliebigen durch Leerzeichen getrennten Anzahl von Symbolen auf der rechten Seite. Jede Ausgabe, die die folgenden Einschränkungen befolgt und genau die Eingabezeichenfolge ableitet, ist gültig.
Beschränkungen
Um Menschen davon abzuhalten, seltsame Dinge zu tun, gibt es eine Reihe von Einschränkungen:
Jedes Nichtterminal muss mindestens zweimal auf der rechten Seite einer Regel erscheinen. Beispielsweise ist die folgende Grammatik für die Eingabe
abcabc
unzulässig, da Regel 12 nur einmal vorkommt:10=12 11=a b c 12=11 11
Keine Folge von zwei benachbarten Symbolen darf mehr als einmal auf allen rechten Seiten aller Regeln erscheinen, außer wenn sie sich überlappen. Beispielsweise ist die folgende Grammatik für die Eingabe
abcabcbc
unzulässig, da die Sequenzbc
zweimal angezeigt wird:10=11 11 b c 11=a b c
Eine gültige Grammatik wäre:
10=11 11 12 11=a 12 12=b c
Ihr Programm muss für jede gültige Eingabe, die nicht länger als 65535 Byte ist, in weniger als einer Minute beendet werden.
Wie üblich dürfen Sie keine Funktion Ihrer Sprache oder Bibliotheksfunktion verwenden, die die Lösung trivial macht oder einen großen Teil davon implementiert.
Beispieleingabe
Generieren Sie eine Probeneingabe mit dem folgenden C-Programm.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
unsigned int i,j = 0,k;
if (argc != 3
|| 2 != sscanf(argv[1],"%u",&i)
+ sscanf(argv[2],"%u",&k)) {
fprintf(stderr,"Usage: %s seed length\n",argv[0]);
return EXIT_FAILURE;
}
srand(i);
while(j < k) {
i = rand() & 0x7f;
if (i > 34 && i != 127) j++, putchar(i);
}
return EXIT_SUCCESS;
}
Die vom obigen Programm erzeugte Beispieleingabe führt normalerweise nicht zu guten Komprimierungsergebnissen. Verwenden Sie möglicherweise menschlichen Text oder Quellcode als Beispieleingabe.
Gewinnkriterien
Das ist Code Golf; Das Programm mit dem kürzesten Quellcode gewinnt. Schreiben Sie für zusätzliche Gutschrift ein Programm, das die Eingabe aus der Ausgabe rekonstruiert.
quelle
Antworten:
GolfScript,
111108 ZeichenDies ist ein ziemlich ungeschickter Ansatz mit GolfScript. Die zweite Version bietet eine viel bessere Leistung als die erste. Es ist viel länger als der beabsichtigte Code, aber meine Implementierung hatte verschachtelte do-Schleifen und dies verursachte Probleme mit dem Interpreter.
Beispiele:
quelle
Zurückgezogen - Der Algorithmus kann nicht alle Fälle behandeln.
C, 422 (behoben, um Dups in der Ausgabe zu entfernen und Zeichen zu löschen)Die erste Implementierung beginnt mit dem Golfen.
Da die Regeln es nicht erfordern, diesen Brute-Force-naiven Ansatz tatsächlich zu komprimieren, reicht dies aus ...
Kann die Länge von 65535 innerhalb von 10 Sekunden verarbeiten
Probelauf:
quelle