人間のテキストやソースコードなど、ある種のデータを直線的な文法で圧縮することができます。基本的には、言語が1語のみの文法、つまり非圧縮データを作成します。このタスクでは、このデータ圧縮方法を実装するプログラムを作成する必要があります。
入力
入力は65535バイト以下の文字列です。入力が正規表現[!-~]+
(つまり、空白を除いた少なくとも1つの印刷可能なASCII文字)に一致することが保証されています。
入力例は
abcabcbcbcabcacacabcabab
出力
出力は、正確に1つの単語(入力)を記述する文法を形成する一連のルールです。各非終端記号は、9より大きい10進数で表されます。開始記号は記号番号10です。入力例に対応する出力例を以下に示します。その構文については、以下でさらに説明します。
10=11 11 12 12 11 13 13 11 14 14
11=a 12
12=b c
13=a c
14=a b
各ルールには<nonterminal>=<symbol> <symbol> ...
、右側に任意の空白で区切られた数の記号が付いた形式があります。以下の制限に従い、入力文字列を正確に導出する各出力は有効です。
制限事項
人々が奇妙なことをするのを止めるために、いくつかの制限が行われています:
各非終端記号は、ルールの右側に少なくとも2回出現する必要があります。たとえば、
abcabc
ルール12は1回しか出現しないため、次の入力の文法は無効です。10=12 11=a b c 12=11 11
2つの隣接するシンボルのシーケンスは、重複しない限り、すべてのルールのすべての右側に複数回出現することはできません。たとえば
abcabcbc
、シーケンスbc
が2回出現するため、次の入力の文法は無効です。10=11 11 b c 11=a b c
有効な文法は次のとおりです。
10=11 11 12 11=a 12 12=b c
プログラムは、65535バイト以下の有効な入力ごとに1分未満で終了する必要があります。
いつものように、あなたの言語の機能や、ソリューションを簡単にする、またはその大部分を実装するライブラリ関数を使用することはできません。
入力例
次のCプログラムでサンプル入力を生成します。
#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;
}
上記のプログラムによって生成されたサンプル入力は、通常、良好な圧縮結果にはなりません。入力例として、人間のテキストまたはソースコードの使用を検討してください。
受賞基準
これはコードゴルフです。ソースコードが最も短いプログラムが優先されます。追加のクレジットとして、出力から入力を再構築するプログラムを作成します。