トップページ⇒tech
992コメント329KB

【2ch】圧縮アルゴリズム【オリジナル】

■ このスレッドは過去ログ倉庫に格納されています
00011NGNG
おい、おまえら圧縮ソフト作ってみませんか?
中途半端に圧縮されて拡張子が.2ch
0558デフォルトの名無しさんNGNG
結局突き詰めていくと、
逆転文字列をブロックソートした状態になるんじゃないか?
0559540NGNG
>>556
「aの数:6個、bの数:2個、cの数:4個より」
というのは、デコード時の入力データ「abccbaccaaaa」
の各記号の個数を数えただけです。

エンコード時、最初と最後にaを付け加えることにより、
上のように単純に数えることができると考えたんだと思いますが、
余計だったかもしれません。
理屈は>>557の通り。


> 逆転文字列をブロックソートした状態になるんじゃないか?
ですね。
出力結果がブロックソート法より良くなることは無いです。
0560デフォルトの名無しさんNGNG
みんな既存の考え方にとらわれすぎ!

新しい発想でかんがえようよ!

定石やあるゴリ図無なんてクソ倉枝よ!
0561デフォルトの名無しさんNGNG
もう全部算術圧縮でいいよ。
0562デフォルトの名無しさんNGNG
>>561
符号化はもうほとんど算術符号になってるよ。
一部の分野でGolomb符号などが使われているくらい。

今問題にしているのはモデル化の話。
0563デフォルトの名無しさんNGNG
>>561
算術符号は特許問題がやっかいなので使わぬが吉。
RangeCoderにしとけ。
0564デフォルトの名無しさんNGNG
>>563
RangeCoderも白っぽいけど灰色という罠
0565デフォルトの名無しさんNGNG
ソースを書こうよ
0566これでええやんけNGNG

// 希望の圧縮率にできる限り近い圧縮をおこなっちゃうよっ
bool compresser(void *soce //圧縮対象メモリ
 ,int soce_size   //圧縮対象メモリサイズ
 ,void *dest    //展開先メモリ
 ,int dest_size   //展開先メモリサイズ
 ,int compress_rate) //希望の圧縮率
{
  if( compress_rate<1 || 99<compress_rate ){
    printf("1〜99 の間で指定しろや!");
    return false;
  }

  for(int i=0,w=0; i<soce_size; i++){
    if( (rand()%100) > compress_rate )  continue;

    if( dest_size>=w ){
      ptinrf("展開先ちゃんと確保しろや!");
      retunr false;
    }
    dest[w++] = soce[i];
  }

  print("%d%に圧縮しますた[ハート]",w*100/soce_size);
  return true;
}
0567デフォルトの名無しさんNGNG
確かに非可逆圧縮だな。
0568デフォルトの名無しさんNGNG
圧縮率間違ってないか?
99を指定すると無圧縮に…
0569デフォルトの名無しさんNGNG
File file = new File(filename);
file.open();String content = file.readAll();file.close();
file.rename(Base64.encode(content));
file.open();file.write(filename);file.close();
0570デフォルトの名無しさんNGNG
      ∧_∧      ∧_∧
     _( ´∀`)    (´∀` )
  三(⌒),    ノ⊃    ( >>1 .)   糞スレは  
     ̄/ /)  )      | |  |
    . 〈_)\_)      (__(___)
         ∧_∧  .∧_∧
         (  ´∀) (´∀` )
       ≡≡三 三ニ⌒) >>1 .)    立てるなって
        /  /)  )  ̄.| |  |
        〈__)__)  (__(___)
           ∧_∧  ,__ ∧_∧
          (    ´)ノ ):;:;)∀`)
          /    ̄,ノ'' >>1 . )   言ってるだろうが
         C   /~ / /   /
         /   / 〉 (__(__./
         \__)\)
                      ヽ l //
            ∧_∧(⌒) ―― ☆ ―――
            (    ) /|l  // | ヽ   ヴォケがーー!
           (/     ノl|ll / / |  ヽ
            (O  ノ 彡''   /  .|
            /  ./ 〉
            \__)_)
0571566NGNG
>>568
おお、そだな。 0-99の乱数発生だな。
rand関数 滅多につかわんので、まちがえちまった。 % 演算把握の問題って向きもあるが。

> if( ((rand()%100)+1) > compress_rate )  continue;

こんな感じでかんべんしてくれ。
0572デフォルトの名無しさんNGNG
540のは面白いと思う。1次の文脈だけ利用するんだね。

BlockSortingみたいにMoveToFrontにして前の出力との
位置の差を算術符号かstart-step-stop符号で符号化す
れば圧縮できるだろう。

たぶん、素の(0次の)MTFよりは良くて、BlockSortよりは
悪い、実に中途半端な圧縮率が得られてスレの主旨に
ぴったりでは。速度も中間になる(BSよりはだいぶ速い)
はず。
0573デフォルトの名無しさんNGNG
そんなんで圧縮できるわけねーだろ。
0574デフォルトの名無しさんNGNG
>>573
圧縮は当然できるだろ。
0次のMTFと比べてどうかはわからんが。
0575デフォルトの名無しさんNGNG
できるわけねーだろ。
なんでできると思うんだ?
0576540NGNG
>>572
1次に限らずとも可能ですよ。
おっしゃるとおり、2次程度の540 → MTF → 算術でそれなりに縮みます。

大量の文脈を使用する場合、>>547のソースでいう code_count の
扱いが問題になると思います。
0577デフォルトの名無しさんNGNG
>>576
いや、これ次数を高くしたらつまんないと思う。
普通のPPMコーダとかの、高次混合モデルを
作るやつの方が良くなっちゃう。

単にバッファを1MBくらいに大きくしてみれば?
0578540NGNG
> いや、これ次数を高くしたらつまんないと思う。
そうかもしれませんね。
ただ、1次と2次の性能の差はかなり大きかったです。

バッファは8Mでテストしたと思いますが、
これを増やしてもそれほど意味は無いはず。
0579デフォルトの名無しさんNGNG
>>578面白い圧縮法ですね。bigramに限ったブロックソートみたいな。

>>572
0次と1次じゃなくて、1次と2次では? 540のアルゴリズムは2次の
エントロピーコーダですよね。
0580デフォルトの名無しさんNGNG
すごいすごい。めどがついたら、ぜひupして欲しい。
0581デフォルトの名無しさんNGNG
http://piza.2ch.net/tech/kako/980/980257360.html
こんなのがあった…。
0582デフォルトの名無しさんNGNG
ttp://210.153.114.238/img-box/img20021027004155.zip
>>572を実装しますた。頻度表も>>552と同じような方法で追い出し。

SSS符号はイマイチな予感(LZFGで使ってるの位しか知らない…)。
次のアプローチとしてはSSSの代わりに連長+RangeCoderを導入するか
二次化なんだろうけど、さて。
0583デフォルトの名無しさんNGNG
>>582
イマイチなのは当然だろう。
>>572は圧縮でもソートでもない。無意味な作業。
0584デフォルトの名無しさんNGNG
( ´_ゝ`)フーン



では次のネタどうぞ。
0585デフォルトの名無しさんNGNG
単にシャッフルしてるだけじゃん。
なんでこれで圧縮できると思うの?
0586デフォルトの名無しさんNGNG
>>585
MTFとは違う特徴をもったアルゴリズムを作りたかったからだろう。
実際、MTFでは理論的・実践的にいまいちな場面というものが存在する。
普通の定常無記憶情報源での比較ではなく、
特殊な状況で役に立つアルゴリズムというのを考えてみるのもよい。

オレは上の関連で論文を一本書いた。
0587デフォルトの名無しさんNGNG
このスレには

情報理論の分かるヤツと
分からないけどとりあえずコードを書いて分かったつもりになってるヤツと
分からないのでひたすら煽るだけのヤツがいゐ…
0588デフォルトの名無しさんNGNG
>>587
分からないのでひたすら煽るだけのヤツ
0589デフォルトの名無しさんNGNG
>>588
同意。何かを分析した気になっている。
0590デフォルトの名無しさんNGNG
情報理論をわかっているっぽい人には、
とりあえず情報理論の教科書でもあげてもらうか。
0591デフォルトの名無しさんNGNG
>>590
そして逆ギレ。
0592デフォルトの名無しさんNGNG
>>540
限定ソート?
0593590NGNG
>>591
いや、オレもいちおー専門だから。
0594デフォルトの名無しさんNGNG
せんもん・・・何にもせんもん・・・
0595540NGNG
>>592
一言で言うとそうなりますね。
単なる最大限定ソート。
次数を上げるとまさに限定ソートそのものです。

M.BurrowsとD.J.Wheelerが最初に考えたのが
540のような感じじゃないかなと思ったり。
0596デフォルトの名無しさんNGNG
(´-`).oO(7行のSさんってこのスレにはいないのかな…?)
0597590NGNG
持っている本

韓太舜・小林欣吾、情報と符号化の数理、培風館
植松友彦、現代シャノン理論、培風館
情報理論とその応用学会編、情報源符号化 無歪みデータ圧縮

他にはデータ圧縮関連の和書洋書、アルゴリズム関連の本、
情報処理学会、電子情報通信学会、IEEE、などの論文集。
0598デフォルトの名無しさんNGNG
540で圧縮できないという人は何を根拠に言ってるのでしょう。

MTFで「何記号前に出現したか」の平均符号長は1次エントロピーに
漸近するのに対し、540だと2次エントロピーに漸近すると思うのですが。
0599デフォルトの名無しさんNGNG
>>598
わかっている人は、
MTFやブロックソートと同様、記号をかき混ぜているだけで長さは変わらない
ということがちゃんとわかっているから、大丈夫だろうけど。

わかっていない人は、
そもそも>>540の手法とMTFやブロックソート法との比較もわからないのだと思う。
0600デフォルトの名無しさんNGNG
いや、>>540 が面白いこと考え付いたのが悔しくて
わからない人の振りをして荒らしてるだけかも…
ってのは考えすぎか。
0601デフォルトの名無しさんNGNG
いや、実装してみてもやっぱり大して圧縮できないんだけど。
0602デフォルトの名無しさんNGNG
つーか、本当に、何を根拠に圧縮できると思うの?
MTFは記号の出現頻度を故意に変えることで圧縮率を高めるし、
ブロックソートは同じ記号をまとめることで、圧縮率を高める。

だけど、これは本当に単に並べ替えてるだけ。
なぜこれで圧縮率が変わると思えるのか、それが知りたい。
どういう理論?
0603デフォルトの名無しさんNGNG
>>601
たとえ数パーセントでも圧縮されるのなら、>>1の出した仕様に適合すると思われ。
0604デフォルトの名無しさんNGNG
いーからとっとと作ってうpしろよ
仕事おせーな
0605デフォルトの名無しさんNGNG
abababababababab
↓
a:bbbbbbbb
b:aaaaaaaa
↓
符号化する、だろ。
0606デフォルトの名無しさんNGNG
馬
馬馬 → 驫


1/3に圧縮できますた
0607デフォルトの名無しさんNGNG
>>602
だから逆転した文脈1次モデルだろ?
0608デフォルトの名無しさんNGNG
ちょいと試してみた。Calgury Corpus全体の1次エントロピーは5.362bits/symbol
1次のハフマンで最適に符号化したとして5.868bits/symbol
(符号表その他のオーバーへッドは除く。以下同じ。)

単純なMTFの出力の1次エントロピーは5.119bits/symbol
後段にハフマンを用いると5.591bits/symbol

540+MTFの出力の1次エントロピーは、
ブロックサイズ(bytes) エントロピー(bits/symbol) ハフマン符号(bits/symbol)
4096 4.142 4.577
16384 4.043 4.489
65536 4.005 4.460
...
全部1ブロックに入るとき 3.994 4.452

なので、算術符号を用いれば最高で3.994bits/symbolくらいまで圧縮できる。
ハフマンだと4.452bits/symbol

面白いのは最後段にStart-Step-Stop符号を用いたときで、全部1ブロックに入
るとき、
(3, 2, 9)符号を用いると4.830bits/symbol
(2, 2, 8)符号を用いると4.509bits/symbol
(1, 2, 9)符号を用いると4.388bits/symbol
と、符号によってはハフマンより良い結果になる。

ちなみに、gzip -9だと2.606bit/symbol
bzip2 だと2.190bits/symbol
まで圧縮される。
0609デフォルトの名無しさんNGNG
>>602
こんな簡単なことが本当に分からんなら
もう口を出すな。
0610デフォルトの名無しさんNGNG
>>603
いや、この方法自体では圧縮はされないどころか、かえってデータ量が増える。

だから、二次圧縮後のサイズを比べてみたんだけど、この方法を使わない場合に比べて、
ほとんど差は無かった。
こう書くと、「ちょっとは差があったのか?」と聞かれると思うが、それは言葉のあやで、
この方法を使った方が小さくなることもあり、大きくなることもあり、
平均してみると、使わない方がどちらかというと小さくなる。
「使わない方が大きくなる」と言うほどは差がないので「ほとんど差は無かった」と書いただけで、
使った方が少しは小さくなるというわけではない。
で、どういう理論を思っているのかを聞いたわけ。

例えば、>>605のようなデータは、元のデータがもともと圧縮率が高く、ab2で表せる。
二次圧縮後に差が出るとは思えない。
0611デフォルトの名無しさんNGNG
ちなみに、>>608が延々と書いてあることを訳すと、
「ハフマンより算術符号の方が圧縮率が高い」ということね。
0612608NGNG
>>611
> 「ハフマンより算術符号の方が圧縮率が高い」ということね。
もう一つ付け加えると
「540+MTF+SSSは、立派な圧縮アルゴリズムといえる」ということだ。
(少なくとも、1次のハフマンや単純なMTFよりは圧縮率が高い。)
0613608NGNG
参考までに、テストに使ったコード(最初の段)を抜き出しておく。
このあとMTF+(arithmetic or huffman or SSS)してくれ。
 struct chain { struct chain *next; }; /* ただのchain */
 int i, count;
 unsigned a;
 struct chain *p, *list, **head, **tail;
 unsigned char *buffer;
 if ((buffer = malloc(block_size + 1)) == NULL ||
   (list = calloc(sizeof(struct chain), block_size)) == NULL ||
   (head = calloc(sizeof(struct chain), 256)) == NULL ||
   (tail = calloc(sizeof(struct chain), 256)) == NULL) {
  /* エラー */
 }
 while ((count = fread(buffer, 1, block_size, stdin)) > 0) {
  putchar(buffer[0]);
  buffer[count] = buffer[0];
  for (i = 0; i < 256; i++)
   head[i] = NULL;
  for (i = 0; i < count; i++) {
   a = buffer[i];
   if (head[a] == NULL)
    head[a] = tail[a] = list + i;
   else
    tail[a]->next = list + i;
   list[i].next = NULL;
   tail[a] = list + i;
  }
  for (i = 0; i < 256; i++)
   for (p = head[i]; p != NULL; p = p->next)
    putchar(buffer[p - list + 1]);
 }
0614デフォルトの名無しさんNGNG
やってみたが、やっぱり圧縮率は変わらないぞ。
0615608NGNG
復号化。MTFと(arith or huff or SSS)の復号は済んでるとする。
 int i, count;
 unsigned a;
 unsigned char *buffer;
 unsigned *ptr;
 if ((buffer = malloc(block_size + 2)) == NULL ||
   (ptr = calloc(sizeof(unsigned), 257)) == NULL) {
  /* エラー */
 }
 while ((count = fread(buffer, 1, block_size + 1, stdin)) > 0) {
  buffer[count] = buffer[0];
  for (i = 0; i < 257; i++)
   ptr[i] = 0;
  for (i = 1; i < count; i++)
   ptr[buffer[i] + 1]++;
  for (i = 0; i < 256; i++)
   ptr[i + 1] += ptr[i];
  a = buffer[0];
  for (i = 1; i < count; i++) {
   putchar(a);
   a = buffer[ptr[a]++ + 1];
  }
 }
0616608NGNG
callocの引数の順序が逆だった…欝
結果には影響ないけどね。
0617デフォルトの名無しさんNGNG
一つ聞きたいんだけど、どういうデータで比較してるの?
俺はCのソース使ってほとんど差がでないんだけど。
0618608NGNG
だからCalgury Corpusだってば。
データ圧縮の標準データセット。
これ知らないなら本当にモグリだな。
0619デフォルトの名無しさんNGNG
>>617
もしかして対象データのサイズが小さいとか。
どんな手法でもそうだけど、数十バイトを半分にするのは、
数百メガバイトを半分にするよりもいくぶん難しいよ。
0620デフォルトの名無しさんNGNG
自分の知っていることを書いてモグリって言う奴が多いよな。
自分が知っていることは相手も知っていると思うんだろうか。
0621デフォルトの名無しさんNGNG
最近出まわってる7zip形式って何?
0622デフォルトの名無しさんNGNG
Mozillaのソース(約1万1千行, 334294バイト)でやってみた。

MTF+SSS(3,2,9) 254543バイト
540(ブロック64KB)+MTF+SSS(1,2,9) 170454バイト
0623デフォルトの名無しさんNGNG
おいおい。カルガリコーパスは本当に常識だよ。
圧縮プログラムの比較はたいていこれを使う。

>>618はスペル間違えてるけどな(w
(正しくはCalgary corpus)
0624デフォルトの名無しさんNGNG
Calgury Corpusって何?
初めて聞いたよ。
俺ってモグリだから、Calgary Corpusくらいしか知らねーや。
0625デフォルトの名無しさんNGNG
音 たむさんの「awareness」 っていう作品が見れるHP知りませんか?
誰か教えて下さい、お願いします。
0626デフォルトの名無しさんNGNG
使い慣れない単語だとスペルミスがあるんだよね。
0627デフォルトの名無しさんNGNG
小さいCソース(90行)でやってみた。
元: 1920バイト
MTF+SSS: 1470バイト
540+MTF+SSS: 1022バイト
0628デフォルトの名無しさんNGNG
結局540で圧縮できないとか騒いでたやつは
何が理解できなかったの?
2次エントロピーというのが理解できないとか?
0629デフォルトの名無しさんNGNG
>>628
いや、試してダメだったと言ってるって事は、
情報理論が理解できてないだけでなく
アルゴリズムも理解できてないらしい。
0630デフォルトの名無しさんNGNG
全く理解できない。
なんで俺のところではうまくいかないんだ?
本当に他のところではうまくいってるのか?
ちょっと実行ファイル出してみろよ。
0631じゃ、ちょとだけNGNG
MZ
0632デフォルトの名無しさんNGNG
・圧縮率1/2のケース
女男女男女男女男女男女男 → 娚娚娚娚娚娚

・圧縮率1/3のケース
女男女男女男女男女男女男 → 嫐嬲嫐嬲
女女女女女女女女女女女女 → 姦姦姦姦
0633デフォルトの名無しさんNGNG
>>630
ネタでした〜
0634デフォルトの名無しさんNGNG
>>630
ところでmove-to-frontとstart-step-stopは理解できてるのか?
ちょっとどういう理解か説明してみ?
0635デフォルトの名無しさんNGNG
Canterbury corpusも使おうYo!
0636デフォルトの名無しさんNGNG
>>630
日頃の行ないが悪いからそういうことになるんだ
0637デフォルトの名無しさんNGNG
とりあえず、なんでエントロピーが低くなると思うのか、それを説明してみろよ。
でなきゃ、実行ファイルを作れるソース全部あげてみろ。
0638デフォルトの名無しさんNGNG
まだ理解出来ねーでやんの(フ゜バカはほっとこうぜ。
0639デフォルトの名無しさんNGNG
>>608は偉い。スペルミスを除いて。

ところでstart-step-stopってどうコーディングすればいいのか分かりましぇん。
いろんなパラメータで実験してるところから見て恐らくstart,step,stopを
渡せばそのパラメータで符号化・複合する汎用ルーチンを使ってるんじゃないか
と思うんだけど、もしそうなら是非見せて欲しい。

 車
車車 → 轟
龍龍 → 龖(たしかこれの1/3圧縮バージョンもあったはずだがWindowsにはない?)
0640デフォルトの名無しさんNGNG
こんなんでどう?read_bits, write_bitsは適当に作って。
long read_bits(size_t nbits);
int write_bits(unsigned long bitvector, size_t nbits);
int flush_bits(void)
int sss_read(int start, int step, int stop)
{
 int bits = start;
 int base = 0;
 int code;
 while (bits < stop && (code = read_bits(1)) != EOF && code == 0) {
  base += (1 << bits);
  bits += step;
 }
 if (code == EOF || (code = read_bits(bits)) == EOF) return EOF;
 return code + base;
}
int sss_write(int start, int step, int stop, int code)
{
 int bits = start;
 int base = 0;
 int limit = (1 << start);
 while (bits < stop && code >= limit) {
  write_bits(0, 1);
  base = limit;
  bits += step;
  limit += (1 << bits);
 }
 if (bits < stop) write_bits(1, 1);
 return write_bits(code - base, bits);
}
0641デフォルトの名無しさんNGNG
>>640
全然圧縮されねーぞ。やっぱネタ?
0642デフォルトの名無しさんNGNG
つーか、適当に「作って」って言ってるんだから、
完成してないんだよな。
完成してないものは試しようがない。
従って、圧縮されたと言ってるのは妄想。
0643デフォルトの名無しさんNGNG
>>640
サンクスコ!! あとでじっくり読んでみます。

>>641
否定派は否定するならするでもっと真面目にやってください。
工夫しないネタは只のゴミです。
0644デフォルトの名無しさんNGNG
中途半端なくらいが一番2chっぽい
0645デフォルトの名無しさんNGNG
無駄に凝ってるのが2chっぽいんだろ?
0646デフォルトの名無しさんNGNG
>>644
でもビット入出力ルーチンも書けない>>642はどうかと思う
あと素っ頓狂なことを言っている>>641もどうかと。
SSS符号は、単なる符号なんだからモデルをちゃんと作らなくちゃ、圧縮できるはずがない。
そのためのMTFであり>>540なんだろうに。
0647デフォルトの名無しさんNGNG
猿でも分かるように説明してみる。
高い頻度で出現する記号ほど出現間隔は短くなる。頻度の偏りが大きいと
間隔の平均値は小さくなる。これを利用したのがMTF。

「1つ前の記号がxであるときの記号aの出現頻度P2(a,x)」は、
単なる出現頻度P1(a)より一般には偏りが大きい。たとえば、Cのソースだと
改行文字の後に#が出てくる確率は、他の文字の後に出てくる確率よりずっと
高い。

なので、640のように「1つ前の記号」ごとにまとめてMTFで出現間隔をとると、
1次のMTFより平均値が小さくなる。

最悪で、前の記号と無関係(P2(a,x)=P1(a))の場合でも、640は1次のMTFと
同じになる。(1ブロックごとに1文字ふえるだけ。)
0648647NGNG
s/640/540/
0649デフォルトの名無しさんNGNG
/* 2chエンコーダ完動ソース (1/3) */
#include <stdio.h>

#define BLOCK_SIZE 65536
#define ALPHA_SIZE 256
#define ALPHA_BITS 8

unsigned long bitbuf;
size_t bufbits;
void write_bits(unsigned long c, size_t bits)
{
 bitbuf = ((bitbuf << bits) | (c & ((1 << bits) - 1)));
 bufbits += bits;
 while (bufbits >= ALPHA_BITS) {
  putchar(bitbuf >> (bufbits - ALPHA_BITS));
  bufbits -= ALPHA_BITS;
 }
}
void flush_bits()
{
 if (bufbits > 0)
  putchar(bitbuf << (ALPHA_BITS - bufbits));
 fflush(stdout);
}
0650デフォルトの名無しさんNGNG
/* 2chエンコーダ完動ソース (2/3) */
void sss_write(int start, int step, int stop, int code)
{
 int bits = start;
 int base = 0;
 int limit = (1 << start);
 while (bits < stop && code >= limit) {
  write_bits(0, 1);
  base = limit;
  bits += step;
  limit += (1 << bits);
 }
 if (bits < stop) write_bits(1, 1);
 write_bits(code - base, bits);
}
int mtf_array[ALPHA_SIZE];
void mtf_write(int alphabet)
{
 int i;
 int u, next_u;

 for (u = mtf_array[0], i = 0; u != alphabet; ) {
  next_u = mtf_array[++i];
  mtf_array[i] = u;
  u = next_u;
 }
 mtf_array[0] = u;
 sss_write(1, 2, 9, i);
}
0651デフォルトの名無しさんNGNG
/* 2chエンコーダ完動ソース (3/3) */
unsigned char buffer[BLOCK_SIZE];
long list[BLOCK_SIZE], head[ALPHA_SIZE];

int main(int argc, char *argv[])
{
 int i, count;
 unsigned a;
 long p;

 for (i = 0; i < ALPHA_SIZE; i++)
  mtf_array[i] = i;
 while ((count = fread(buffer, 1, BLOCK_SIZE, stdin)) > 0) {
  mtf_write(buffer[0]);
  buffer[count] = buffer[0];
  for (i = 0; i < ALPHA_SIZE; i++)
   head[i] = -1;
  for (i = count - 1; i >= 0; i--) {
   a = buffer[i];
   list[i] = head[a];
   head[a] = i;
  }
  for (i = 0; i < ALPHA_SIZE; i++) {
   for (p = head[i]; p >= 0; p = list[p])
    mtf_write(buffer[p + 1]);
  }
 }
 flush_bits();
 return 0;
}
0652デフォルトの名無しさんNGNG
/* 2chデコーダ完動ソース (1/3) */
#include <stdio.h>
#define BLOCK_SIZE 65536
#define ALPHA_SIZE 256
#define ALPHA_BITS 8
unsigned long bitbuf;
size_t bufbits;
long read_bits(size_t bits)
{
 int c;
 while (bufbits < bits) {
  if ((c = getchar()) == EOF) return -1;
  bitbuf = ((bitbuf << ALPHA_BITS) | c);
  bufbits += ALPHA_BITS;
 }
 bufbits -= bits;
 return (bitbuf >> bufbits) & ((1 << bits) - 1);
}
int sss_read(int start, int step, int stop)
{
 int bits = start;
 int base = 0;
 int code;
 while (bits < stop && (code = read_bits(1)) >= 0 && code == 0) {
  base += (1 << bits);
  bits += step;
 }
 if (code < 0 || (code = read_bits(bits)) < 0) return EOF;
 return code + base;
}
0653デフォルトの名無しさんNGNG
/* 2chデコーダ完動ソース (2/3) */
int mtf_array[ALPHA_SIZE];
int mtf_read(void)
{
 int i, v, code;
 if ((code = sss_read(1, 2, 9)) == EOF) return EOF;
 v = mtf_array[code];
 for (i = code; i > 0; i--)
  mtf_array[i] = mtf_array[i - 1];
 mtf_array[0] = v;
 return v;
}

unsigned char buffer[BLOCK_SIZE + 2];
long ptr[ALPHA_SIZE + 1];

size_t read_block(void)
{
 int count, c;
 for (count = 0; count < BLOCK_SIZE + 1 && (c = mtf_read()) != EOF; count++)
  buffer[count] = c;
 return count;
}
0654デフォルトの名無しさんNGNG
/* 2chデコーダ完動ソース (3/3) */
int main(void)
{
 int i, count;
 unsigned a;

 for (i = 0; i < ALPHA_SIZE; i++)
  mtf_array[i] = i;
 while ((count = read_block()) > 0) {
  buffer[count] = buffer[0];
  for (i = 0; i < ALPHA_SIZE + 1; i++)
   ptr[i] = 0;
  for (i = 1; i < count; i++)
   ptr[buffer[i] + 1]++;
  for (i = 0; i < ALPHA_SIZE; i++)
   ptr[i + 1] += ptr[i];
  a = buffer[0];
  for (i = 1; i < count; i++) {
   putchar(a);
   a = buffer[ptr[a]++ + 1];
  }
 }
 return 0;
}
0655デフォルトの名無しさんNGNG
うを、ちゃんと動くじゃんこれ!
しかも(゚д゚)ハヤー!
でも圧縮率はたいしたことないね(w
0656デフォルトの名無しさんNGNG
>>655
それは2ch版の仕様なので、製品版ならば圧縮率は向上します。


などといってみるテスト。
0657デフォルトの名無しさんNGNG
MTFで
・先頭じゃなくて二番目に持ってくる
・テーブルを256通り持って直前の文字で切り替える

少し良くなる(かも知れない)けどぱっとしないなぁ…
■ このスレッドは過去ログ倉庫に格納されています