Most Well-rounded Hash
もっとも練り上げられたハッシュ
受賞者:Qiming HOU
引用元:https://www.ioccc.org/2015/hou/prog.c
審査員・作者による説明:https://www.ioccc.org/2015/hou/hint.html
動作
MD5の計算を行う。
$ gcc -o prog prog.c -lm
$ echo "Hello, world!" | ./prog
746308829575e17c3331bbcb00c0898b
普通のmd5sumの結果と比較すれば、正しいことがわかる。
$ echo "Hello, world!" | md5sum
746308829575e17c3331bbcb00c0898b -
解説
一部のスクリプト言語はしばしば、double
型しか持たない(JavaScript、Lua、BASICなど)。
これをリスペクトして、基本的にdouble
型しか使わないでMD5が計算がされている。
JavaScriptなどではdouble
型に対して論理演算が使えるが、C言語では一切使えないので、難易度は非常に高くなる。
int
が現れるのはprintf()
の返り値と、int main()
の返り値と、配列参照、getchar()
、EOF
だけ。
bool
型も整数型なので、分岐はwhile(!printf("%s",...))
の1つを除いて存在しない。
ループの中は上から下へ真っ直ぐ計算するだけ。
floor()
とceil()
はチートな感じがするので避けたとのこと。
基本的にIEEE 754の浮動小数点数を使って頑張る。
仮数部が52ビット(ケチ表現で53ビット)あるので、32ビット整数を収めることはできる。
4つの補助関数が定義されていて、関数_
は32ビット整数除算、関数Q
は大小比較(d > l
ならば1.0、そうでなければ0.0を返す)、関数’I’は等価比較(等しければ1.0を返す)、関数f
は32ビット整数剰余となっている。
データを読み込んで配列に書き込んだあと、データを1ビットずつ処理するのを1つのループにしているので、C言語力とMD5計算の用法の知識が必要。
MD5は512バイトのチャンクごとに、4つのフェーズの処理を16回ずつ繰り返す、64回のループをする。
このプログラムはさらに、and
やxor
のビット演算のために、フェーズの処理を32回のループに分けて行っていると思う。
おそらくj
が64回のカウンタで、o
にフェーズが入っているが、詳しいことはよくわからなかった。
賞名にMost Well-roundedの語が入っているので、最優秀賞の位置づけだと思われる。