文脈自由文法でデータを圧縮する


9

人間のテキストやソースコードなど、ある種のデータを直線的な文法で圧縮することができます。基本的には、言語が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;
}

上記のプログラムによって生成されたサンプル入力は、通常、良好な圧縮結果にはなりません。入力例として、人間のテキストまたはソースコードの使用を検討してください。

受賞基準

これはコードゴルフです。ソースコードが最も短いプログラムが優先されます。追加のクレジットとして、出力から入力を再構築するプログラムを作成します。


ははは。kolmogorovの複雑さの質問のために、Javaでこれを実装した(ただしゴルフではない)いくつかのバージョンをすでに持っています...
Peter Taylor

@PeterTaylorどの質問を正確に?
FUZxxl 2012年

投稿に値するほど短い答えは必ずしも見つかりません(文法生成戦略と文法エンジンをゆっくりと追加しています)が、そのプロジェクトのコアスクリプトはcodegolf.stackexchange.com/questions/1682、codegolfそれらを試します.stackexchange.com / questions / 6043codegolf.stackexchange.com/questions/ 4191codegolf.stackexchange.com/questions/ 4356およびその他の質問のいくつかのコンポーネント。
Peter Taylor

回答:


3

GolfScript、111 108文字

1/{.}{:^1<{^1$/,2>.{;,)^<.0?)!}*}do-1<.,1>{^1$/[10):10]*0+\+}{;^}if(\}while][0]%.,,]zip{))9+`"="+\~" "*+}%n*

これは、GolfScriptを使用した非常に不格好なアプローチです。2番目のバージョンは、最初のバージョンよりもパフォーマンスが大幅に向上します。意図したコードよりもはるかに長くなりますが、私の実装にはネストされたdoループがあり、これによりインタープリターで問題が発生しました。

例:

> abcba
10=a b c b a

> abcabcbc
10=11 11 12
11=a 12
12=b c

> abcabcbcbcabcacacabcabab
10=11 12 12 13 14 14 c 11 15
11=15 13
12=c b
13=14 b
14=c a
15=a b

1

撤回-アルゴリズムはすべてのケースを処理できません。C、422(出力の重複を削除し、文字を削除するように修正)

最初の実装では、ゴルフを開始します。

ルールでは、このブルートフォースナイーブアプローチを実際に圧縮する必要はないので...

10秒以内に65535の長さを処理できます

n,m[99999];
c,r[99999][2];

g,i,s,t;

main(){
    for(;(m[n]=getchar())>32;n++);

    while(!g){ // loop until no further changes
        g=1;
        for(s=0;s<n-1;s++) {
            for(t=s+2;t<n-1;t++)if(m[s]==m[t]&&m[s+1]==m[t+1]){
                // create rule
                r[c][0]=m[s];
                r[c++][1]=m[s+1];
                g=0;
                // substitute
                for(i=t=s;i<n;i++){
                    if(m[i]==r[c-1][0]&&m[i+1]==r[c-1][1]){
                        m[t++]=-c;
                        i++;
                    }else
                        m[t++]=m[i];
                }
                n=t;
            }
        }
    }

    for(s=-1;s<c;s++){
        printf("%d=",s+11);
        for(t=0;t<(s<0?n:2);t++){
            i=(s<0?m:r[s])[t];
            i<0?printf("%d ",10-i):printf("%c ",i);
        }
        printf("\n");
    }

}

サンプルの実行:

echo abcabcbcbcabcacacabcabab | a.out
10=11 12 13 13 12 14 14 12 12 11 
11=a b 
12=c 11 
13=c b 
14=c a


あなたのコードは仕様に従って動作しません。ルールに違反する出力を生成します。2つの文字のシーケンスが2回出現することはありません。入力abcdabcdを検討してください。また、コードによって入力ストリームから最後のバイトが削除されたようです。両方の影響を観察する例については、こちらをご覧ください:ideone.com/3Xvtyv
FUZxxl

また、サンプル出力は明らかに間違っています。
FUZxxl 2012年

あなたが正しい-私は失敗しました-私が仕事から帰ったら私はそれを見ていきます:P
baby-rabbit

それは私にとって入力から最後のバイトを削除していません-私のサンプル出力は正しいです(私にとって)。 "バグを見つけて"遊んでみましょう!
baby-rabbit

あなたが確実に投稿したサンプル出力は次のとおりです。ルール10の拡張形式はルール14で終わり、ルール14は「ca」で終わります。最後のcは実際には終了前の5ポジションです。
FUZxxl 2012年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.