2017/08/18 00:12

ネタ本を新たに発掘しました。『マイコンとパズルの世界 BASICプログラミング頭の体操』〔小谷 善行, 産報出版, 1981.〕。

プロジェクトの本文や、活動報告についての感想、ご意見、ご質問を、ぜひコメントでお寄せいただければと思います。現在は支援募集期間中であり、本企画の実施期間ではないため、お寄せいただいた感想などについてはリターンとしてではなく、お返事や回答をさせていただきます。

また、私個人についてはこちらをご覧ください。

では本題、前回の続きです。

先の符号ビット表示のみを取り出し、そのまま並べてみます:
符号ビット表示
1111110 1111110
11111110 111111110
0 10
0 10
110 1110
110 1110
11110 111110
11110 111110
1111111110 11111111110
111110 11110
1110 110
1110 110
1110 110
10 0
10 0
10 0

さらに、これを8ビットずつの並びにしてみます:
2進表示
1111 1101   1111 1011   1111 1011
1111 1100   1001 0110   1110 1101
1101 1110   1111 1011   1101 1111
0111 1111   1101 1111   1111 1011
1110 1111   0111 0110   1110 1101
1101 1010   0100 1001
(最後に1ビット、1を付け加えています。)

16進表示
FD FB FB
FC 95 ED
DE FB DF
7F DF FB
EF 76 ED
DA 49

この場合、元の32バイトが、17バイトに収まっています。もっとも、これはデータの部分だけですが。

なお、今回は、圧縮の対象のデータを8bit固定長としましたが、可変長でも構わないことに注意してください。

さて、この16進表示だけでは、元に戻せないので、戻すための辞書も作りましょう。前回の投稿分の、「ここで、これらに次のようにbit単位の符号を割り当てたとします」にこのようなデータがありました:
値  回数  ビット列
00 2   1111110
01 1   11111110
80 1   111111110
02 5   0
40 5   10
04 5   110
20 5   1110
08 3   11110
10 3   111110
1F 1   1111111110
F8 1   11111111110

ここで「回数」は必要ないので削除します。ついでに「ビット列」と「値」も入れ替えてみましょう:
ビット列        値  
1111110     00
11111110    01 
111111110   80 
0           02
10          40
110         04
1110        20
11110       08
111110      10
1111111110  1F 
11111111110 F8 

これを、ビット列の長さで並べ替えます:
ビット列        値  
0           02
10          40
110         04
1110        20
11110       08
111110      10
1111110     00
11111110    01 
111111110   80 
1111111110  1F 
11111111110 F8 

続いて「値」もビット列に直しましょう:
ビット列        値   値のビット列  
0           02  0000 0010
10          40  0100 0000
110         04  0000 0100
1110        20  0010 0000
11110       08  0000 1000
111110      10  0001 0000
1111110     00  0000 0000
11111110    01  0000 0001
111111110   80  1000 0000
1111111110  1F  0001 1111
11111111110 F8  1111 1000

さて、次にこの「ビット列」と「値のビット列」をくっつけます。この場合、「可変長 + 8ビット」という形式に決まっており、かつ「可変長」つまり「ビット列」の部分は “0” で終っていることに注意しましょう:
全体のビット列
0 0000 0010
10 0100 0000
110 0000 0100
1110 0010 0000
11110 0000 1000
111110 0001 0000
1111110  0000 0000
11111110 0000 0001
111111110 1000 0000
1111111110 0001 1111
11111111110 1111 1000

では、これを8ビットずつにくっつけたり分割したりします:
全体のビット列 2進表示
0000 0001  0100 1000  0001 1000
0001 0011  1000 1000  0011 1100
0001 0001  1111 0000  1000 0111
1110 0000  0000 1111  1110 0000
0001 1111  1111 0100  0000 0111
1111 1100  0011 1111  1111 1111
1011 1110  0011 1111
(最後に1を6こ付け加えました。)

これにより辞書の部分は20バイトとなります。

では、これからもとの「辞書」を再現できるかやってみましょう。
まず、1ビットめは「0」ですから、符号は「0」のみで、以下の8ビットは元の値です。その8ビットは「0000 0010」とわかります。その次のビット列は「10」で、それに続く8ビットは「0100 0000」だとわかります。さらにその次のビット列は「110」で、それに続く8ビットは「0000 0100」だとわかります。以下略。

このようにすると、先のデータに対して辞書を加えて、17バイト + 20バイト = 37バイトとなりました。前回の投稿の「最後に8ビットごとの “□” と “■” の並びをそのままバイトに置き換えるとします」の箇所では32バイトでしたので、嬉しい結果ではありませんが、もとのバイト数が少なかったからというところでしょう。辞書は必要ですが、ここではデータ本体32バイトに対して17バイトになったことでよしとしましょう。

これらの例は、すこしばかり不自然な面もありますが、データ表現やデータ圧縮の入口のネタには使えるのではないかと思います。もうすこし工夫が必要ですが。文字、それもアルファベットのようなシンプルなものではなく、漢字にすると、面白さとしては違ってくるかと思います。

興味を持たれましたら、ぜひご支援や、コメントを頂ければと思います。