東大の演習問題に挑戦(2) - 圧縮・解凍編
もう一個いっとこー
課題2-A:データを圧縮・解凍するプログラムを実装せよ。
が・ガンバリマス。
方針
超簡単なランレングス符号でいっときます。
- aaaaというデータがあったら、[4 a]として保存。1個の場合はaとします。
- 日本語は考えないということで、数にあたるデータなら、バイトの1個目をフラグにしておきます。
サボりすぎ!?
圧縮
#include <stdio.h> #include <stdlib.h> int main(void) { int c, d; int n = 1; c = getchar(); while (c != EOF) { d = getchar(); if (c == d) n++; else { if (n != 1) putchar(n | 0x80); putchar(c); n = 1; } c = d; } return EXIT_SUCCESS; }
こんだけ。すげー簡単。
解凍
#include <stdio.h> #include <stdlib.h> int main(void) { int c, d, i; while ((c = getchar()) != EOF) { if ((c & 0x80) == 0x80) { d = getchar(); for (i = 0; i < (c & ~0x80); i++) putchar(d); } else putchar(c); } return EXIT_SUCCESS; }
短いな。
早速
圧縮だけ。
% ./compress abbcccddddeeeee a�b�c�d�e
バイナリになりました。
圧縮&解凍もしてみる。
% ./compress | ./uncompress abbcccddddeeeee abbcccddddeeeee
元に戻った!!
課題とか
- あんまり長いデータだと元に戻りません(汗
- あ、文字側にフラグを付けた方がよかったかも。
- バイナリファイルの取扱いがイマイチよくわかってない事が判明。
- バイナリ上で混在するデータを取り扱えるようになりたいなぁと思う。
まだまだ修行が足りません。
次は飛ばそうかと
スパムフィルタは、
- 実装方法(どんなデータを、どのようにフィルタリングしたらよいか)がよくわからない。
- 類似の問題に出会っているのかわからない。
という理由でトバス。「いかにして問題をとくか」がすげー役立ってるな。
簡単にやるなら、grep -vか。○○にマッチしたら表示しない。受け取らない位しか発想出来ない。
追記 2
追記1を使って、発展バージョンを考えると、
- 例えばa-zA-Zを固定長6ビットに符号化。
- ついでに連長フラグを1ビット。
- で、連長個数、7(任意)ビット割り当てる。
と出来そうだ。更に圧縮可能。
もうちょっと発展バージョンを考えると、
- 符号化には符号化テーブル(木)を作成する。ハフマンとか。SICPに書いてある。
- 連長圧縮ではなく辞書テーブル(木)を使う方法。LZ法とか。組んだことが無い。
もうちょっと発展バージョンは、「木が必要」なのでスゲー大変だ。数学の山がわんさか出てくる。深く突っ込むとヤバイヨ〜。
LZ法は今度やろうと思う。