0

可能な限り最小限のデータで、以下をバイナリ形式に変換する (後で回収する) 必要があります。

my_arr = [
        [128,32 ,22,23],
        [104,53 ,21,25],
        [150,55 ,79,23],
        [104,101,23,8 ],
        [57 ,117,13,21],
        [37 ,135,21,20],
        [81 ,132,23,6 ],
        [81 ,138,7 ,8 ],
        [97 ,138,7 ,8 ]...

数が 399 を超えない

各桁に 0 を使用し (行に 8 つの 0 = 8)、区切り文字として 1 を使用すると、最初の行は次のようになります: 010010000000011000100110010011001000

各数値を 3 桁にパディングし、それぞれを実際のバイナリに変換すると、最初の行は次のようになります。

最初の文字が 4 以上になることはないので、0 を 00、1 を 01、2 を 10、3 を 11 として扱うことで 2 桁を節約できます。最初のオプションの約 90% (平均) ですが、もっと短い方法はありますか?

編集:はい、1と0の文字列として...そして元の整数よりも短くする必要はありません...2つの記号のみを使用してそれを書く最短の方法です

4

3 に答える 3

5

値が 0 から 399 の間で均等に分布している場合、3 つの値を取り、それらを 400 を基数とする 3 桁の整数としてエンコードするのが、かなり適切なエンコードです。つまり、val1 + 400*val2 + 400*400*val3 です。次に、その整数は26ビットにうまく収まります。4 つの連続する 26 ビット値は 13 バイトに収まります。次に、値ごとに平均 13/12 バイトが得られます。

値の分布に偏りがある場合や、繰り返しや相関がある場合を除き、値をさらに圧縮することができます。

詳細に対処するには、エンコードされたシーケンスのバイト数を使用して値の数を決定できますが、これは 3 の倍数ではない場合があります。3 の倍数でない場合は、末尾に 1 つまたは 2 つの値があり、それぞれ 9 ビットとして単純にコード化されます。18 ビットから 26 ビットに値を加算するには 8 ビットかかるため、カウントにあいまいさはありません。

于 2013-01-13T23:36:43.127 に答える
1

良い出発点は、1 と 0 の一定長のブロックを作成することです。これにより、文字列を簡単にデコードできます。

2 進数の 400 は 110010000 です。これは、一定の長さにゼロが埋め込まれたバイナリ表現として各数値をエンコードするために 9 文字を必要とします。

最初の行のエンコード:

var padTo9 = function( bin ){ 
    while( bin.length<9 ){ bin = "0" + bin; } 
    return bin; 
}
[128,32 ,22,23].map( function(i){ return padTo9( i.toString(2) ) }).join('');

/* result:
"010000000000100000000010110000010111"
*/

デコード

"010000000000100000000010110000010111".match(/[0-1]{9}/g).map( function(i){ return parseInt( i, 2 ) });
/* result:
[128, 32, 22, 23]
*/

より短い文字列を取得する唯一の方法は、可変ブロック長を使用することだと思います。これには、制御記号を追加して、次の数字が特定の文字数でエンコードされていることをデコーダーに伝える必要があります。しかし、これらのシンボルは 400 を超えて 9 文字の長さでなければならないので、データがランダムに分散されている場合には役に立たないと思います。

于 2013-01-14T00:34:35.247 に答える