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回のループをする。 このプログラムはさらに、andxorのビット演算のために、フェーズの処理を32回のループに分けて行っていると思う。 おそらくjが64回のカウンタで、oにフェーズが入っているが、詳しいことはよくわからなかった。

賞名にMost Well-roundedの語が入っているので、最優秀賞の位置づけだと思われる。