ダイナミックASCIIエンコーダー!


16

前書き

一部のASCII文字は最近非常に高価です...

お金を節約するために、高価な文字を安価な文字を使用してエンコードするプログラムを作成することにしました。

ただし、キャラクターの価格は頻繁に変更されるため、別のキャラクターをエンコードまたはデコードする必要があるたびにプログラムを変更する必要はありません。より動的なソリューションが必要になります。

チャレンジ

あなたの仕事は、エンコーダーデコーダーの 2つのプログラムを書くことです。

エンコーダは、 5つの安価な文字のリスト、および単一の高価な文字を受け入れる必要があります。

安価な文字で構成される単一の文字列を出力し、高価な文字をエンコードする必要があります。

この文字列 、安価に保つために4文字より長くすることはできません。ただし、エンコードで安価な文字をすべて使用する必要はなく、エンコードの長さは異なる場合があります。


デコーダは、エンコーダによって出力された文字列、および出力高価な文字を受け入れなければなりません。

デコーダは、エンコードされた文字列以外の入力を受け付けません。入力の任意の(有効な)組み合わせに対して、エンコーダの出力から変更せずに動作する必要があります。言い換えれば、デコーダプログラム は、どの文字が高価であるか、または安価であるかを知りません。

得点

最短の組み合わせコードが勝ちます!

ノート

  • すべての文字は、大文字[A-Z]、小文字[a-z]、または数字のいずれかになります[0-9]

  • 安価な文字のリストには重複が含まれません。安価で高価なキャラクターはありません。

  • エンコーダーとデコーダーを同じ言語で記述する必要はありませんが、可能です。プログラムまたは関数を作成できます。

  • 入力および出力は、言語に適した任意の形式である場合があります。

  • 2つのプログラムは、変数またはデータを共有できません。

概要

  • いくつかの安価な文字と高価な文字の入力がエンコーダに与えられます。

  • エンコーダーは、安価な文字列を出力し、高価な文字をエンコードします。

  • デコーダーにはエンコーダーの出力が与えられ、高価な文字が出力されます。

入力:     a, b, c, d, e     f

エンコーダーの可能性:     a     eeee     caec

デコーダ:     f


入力:     a, b, c, d, e     h

エンコーダーの可能性:     bc     cea     eeaa

デコーダ:     h


入力:     q, P, G, 7, C     f

エンコーダーの可能性:     777     P7     PPCG

デコーダ:     f


これは本当に私である可能性があり、この質問がある場合は謝罪しますが、安価な文字でメッセージをどの程度正確にエンコードする予定ですか?5つの安価な文字のASCIIコードの追加?実際、生成されたすべてのエンコーディングの可能性のためにデコーダがデコードする必要がある場合にのみ、この質問の根拠があります。
コール

明確にするために:エンコーダーの可能性は単なる例であり、必要に応じて各文字をエンコードできますか?
デニス

@Dennisはい、これらは単なる例です。
-jrich

@Cole実際のアルゴリズムを提供することなく、それがここでの主な課題であるため、私はそれが可能であると信じています。A239914によると、エンコードできるのは62の高価な文字だけであり、これら4つのASCII文字で最大92文字をエンコードできます。(これに関するPhiNotPiのサンドボックスコメントのおかげです-エンコードできる数を正確に計算しませんでした)
-jrich

@UndefinedFunctionあなたが意図したことを理解しました:デニスの質問は、私が混乱していたことに答えました。
コール

回答:


5

Pyth、46バイト

エンコーダー、22バイト

@smfql{Td^<Szd4S4-Cw48

デコーダー、24バイト

C+48xsmfql{Td^<sS{zd4S4z

うわー、それは完璧にフィットします。75の異なるチャー組み合わせ及び75のチャー範囲
Jakube

両方のプログラムで1バイトごとに置き換えS4T保存できると思います。
ジャクベ

7

CJam、55 50 48 47バイト

エンコーダー、24 22 21バイト

l$:L4m*{$L|L=},rc'0-=

オンラインでお試しください。

デコーダー、31 28 27 26バイト

4_m*{$4,|4,=},l_$_|f#a#'0+

オンラインでお試しください。


使用しているCJam構文シートはありますか?sourceforgeの1つと他のPDFチートシートには、使用するすべての文字が含まれているわけではありません'
発光

'演算子ではありません。あなたはそれを見つけることができます構文ページでます
デニス

4

gawk、163 + 165 = 328

gawk 4.1.1でテストしましたが、古いgawkバージョンでも動作するはずです。mawkを使用するには、わずかに変更(延長)する必要があります。

エンコーダー(163):

{for(gsub(", ",_);sprintf("%c",++r)!=$NF;asort(a))split($1,a,_);r-=r>64?53:46;for(k=4^5;r-=_~i;j=_)for(i=++k;gsub(++j,_,i);)split(k,b,_);for(j in b)printf a[b[j]]}

デコーダー(165):

{split($1,a,_);for(i in a)d[a[i]]=a[i];asort(d);for(k=4^5;c!~$1;x+=_~i){i=++k;for(c=j=_;gsub(++j,_,i);split(k,b,_));for(g in b)c=c d[b[g]]}printf"%c",x+(x>10?54:47)}

まあ、それは動作しますが、これはこのための最良のアプローチではないかもしれないことを認識しています。私は4つしか使っていないので、5番目の安価な手紙が何のためにあるのか分かりません。

これらは1回限りの使用です。2番目のコードを入力する場合は、それらを再起動する必要があります。エンコードする入力には、コンマの後のスペースが必要です。

私が考えたこと

私の最初の質問は、「デコーダーがこれらの4つの文字から何を得ることができるか?」でした。(私はそれらをa、b、c、dと呼びます)、私の最初のアイデアは次の関係から6ビットの情報を取得することでした:

a>b
a>c
a>d
b>c
b>d
c>d

うわー、6ビット、それは完璧です!私はそれが天才だと思ったが、テストはこれがうまくいかないことを示した。可能な組み合わせは24のみです。くそー。

次のステップは、私がすでに知っていたことに基づいて、数えようとすることでした。したがって、文字列に現れる最初の文字は0になり、文字列に挿入される2番目の文字は1になります。しかし、必要な62の組み合わせに到達することはできません。

0000
0001
0010
0011
0012
0100
0101
0102
0110
0111
0112
0120
0121
0122
0123

しかし、私はとにかくアイデアが好きです。

それで、入力の文字が既にリレーションを持っているので、これら2つを組み合わせることができ、値を与えるためにそれらが導入されるまで待つ必要がないので、私は驚いた。

使い方

注:これはゴルフバージョンの正確な動作ではなくなりましたが、原則は変わりません。

デコーダーの場合:

配列にインデックスが含まれ、そのインデックスには4桁の数字がすべて含まれ、その数字の最大桁数はその数字の個別の桁数より大きくありません。その条件を満たす75の異なる4桁の番号があります。これまでのところ、それらを構築する方法がわからなかったので、私はそれらをブルートフォースしました。これらを見つけている間、私はそれらに高価なキャラクターをアスキー的順序で割り当てます。

次に、入力文字列のすべての文字を数字に置き換えます。最小(たとえば、「a」よりも「B」が小さい)が1になり、2番目に小さいものが2になるなど、最大4になります。もちろん、入力に含まれる異なる文字数、結果の文字列になります。

次に、その文字列をインデックスとして持つ配列要素を単に印刷します。

エンコーダはそれに応じて機能します。

使い方

awk bash行コマンドでコードを直接コピーするか、「encode.awk」と「decode.awk」の2つのファイルを作成し、それに応じてコードを貼り付けます。または、次のコードを使用することをお勧めします。このコードは、en / decodingの後に自動的に終了するか、最後のexitコマンドを削除して複数回使用できます。

encode.awk

{
    if(!x) # only do first time
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:0)++a[p];
            length(a)>=m&&i!~0?c[(x>9?55:48)+x++]=i:_
        }
    r=u=_; # clear reused variables 
    for(gsub(",",FS);sprintf("%c",++r)!=$NF;); # more flexible concerning
    --NF;                                      # spaces in input
    split($0,b);
    asort(b);
    split(c[r],a,_);
    for(j in a)u=u b[a[j]]; # prettier printing than golfed version
    print u
    exit # <=== remove to encode input file
}

decode.awk

{
    if(!x) # only do first time 
        for(i=1e3;i++<5e3;delete a)
        {
            for(m=j=0;p=substr(i,++j,1);p>m?m=p:_)++a[p];
            length(a)>=m&&i!~0?c[i]=sprintf("%c",(x>9?55:48)+x++):_
        }
    delete t; delete d; o=_; # clear reused variables 
    split($1,a,_);
    for(i in a)t[a[i]]=1;
    for(i in t)d[++y]=i;
    asort(d);
    for(i in a)for(j in d)if(d[j]~a[i])o=o j;
    print c[o]
    exit # <=== remove to encode input file
}

以下に使用例を示します。

me@home:~/$ awk -f encode.awk
w, 0, R, 1, d X
10R1
me@home:~/$ awk -f decode.awk
10R1
X

ゴルフバージョンを使用する場合、各コンマの後にスペースが必要であることを忘れないでください。

必要に応じて、この短く汚いスクリプトを使用してサンプルデータを生成できます。

BEGIN{
    for(srand();i++<1000;)
    {
        erg="";
        for(j=0;j++<5;)
        {
            while(erg~(a[j]=substr(c="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",rand()*62+1,1)));
            erg=erg a[j]
        }
        print a[1]", "a[2]", "a[3]", "a[4]", "a[5](rand()>.5?" ":rand()>.5?"  ":"   ")substr(c,rand()*62+1,1)
    }
}

のような面白いことをする

me@home:~/$ awk -f gen.awk|awk -f encode.awk|awk -f decode.awk|sort -u|wc -l
62

私はこれをプログラミングのパズルとしてもっと見ました。よく文書化された読みやすいコードから多くのことを学ぶことができるので、ここのほとんどすべてがゴルフであるのは少し悲しいと思いますが、それは私の意見です。そして、私は要求されたようにそれをゴルフしました;)


それをテストする方法は?いくつかの例を共有してください。
シュラヴァンヤダフ

素晴らしい説明のために+1!この問題にアプローチする方法はたくさんあるようです:)
jrich

1
これは、独自の弱い組み合わせ(最大桁が桁数より大きくないことを説明した)を総当たり攻撃で実行できることを実現できなかったことを除いて、私の思考プロセスに非常に似ていました。フォロースルーの栄誉。
パトリックロバーツ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.