IOCCC、すごいよねえ。
公式サイトに行けば、昔からの入賞作品を見ることができる。
名作揃いだと思うのだが、個人的に特に好きなのが、1992年のBrian Westleyさん(aka Merlyn LeRoyさん)の作品。(ソースコード)
main(l
,a,n,d)char**a;{
for(d=atoi(a[1])/10*80-
atoi(a[2])/5-596;n="@NKA\
CLCCGZAAQBEAADAFaISADJABBA^\
SNLGAQABDAXIMBAACTBATAHDBAN\
ZcEMMCCCCAAhEIJFAEAAABAfHJE\
TBdFLDAANEfDNBPHdBcBBBEA_AL\
H E L L O, W O R L D! "
[l++-3];)for(;n-->64;)
putchar(!d+++33^
l&1);}
古い仕様のCで書かれているが、GCC 4.9.3で正常にコンパイルできることは確認している。
cc westley.c
正常にコンパイルできたら動かしてみよう。例えばこんな感じで。
(動かす際には横幅80文字の端末を使う必要があるので注意)
a.out 35 135
出力はこんな感じ↓

しばらく出力を眺めて、何が書かれているのかを理解してから、もう一度ソースコードを見返した時に衝撃を受けた。
すごいよね~
このソースコードを見やすいものに書き換えて理解してみる。
まずは普通にインデントしてみる。
main(l,a,n,d)
char**a;
{
for(d=atoi(a[1])/10*80-atoi(a[2])/5-596;
n="@NKA"
"CLCCGZAAQBEAADAFaISADJABBA^"
"SNLGAQABDAXIMBAACTBATAHDBAN"
"ZcEMMCCCCAAhEIJFAEAAABAfHJE"
"TBdFLDAANEfDNBPHdBcBBBEA_AL"
" H E L L O, W O R L D! "[l++-3];)
for(;n-->64;)
putchar(!d+++33^l&1);
}
これだけでも見通しが良くなるんだ。
さらにもうちょっと見やすくしてみる。
main(int argc,char** argv) {
int n,d;
for(d=atoi(argv[1])/10*80-atoi(argv[2])/5-596;
n="@NKA"
"CLCCGZAAQBEAADAFaISADJABBA^"
"SNLGAQABDAXIMBAACTBATAHDBAN"
"ZcEMMCCCCAAhEIJFAEAAABAfHJE"
"TBdFLDAANEfDNBPHdBcBBBEA_AL"
" H E L L O, W O R L D! "[argc++-3];)
for(;n-->64;)
putchar(!d+++33^argc&1);
}
一番トリッキーなのは
putchar(!d+++33^argc&1);
だと思う。括弧を使って見やすくしてみる。
putchar(((!(d++)) + 33) ^ (argc&1));
面白いコードだねえ。
!(d++)の!は論理式の否定。dが0の場合には!(d++)は1、dが0以外の場合には!(d++)は0。
argc&1はargcが偶数なら0、奇数なら1。
^は排他的論理和なので、((!(d++)) + 33)の最下位ビットを反転したりしなかったりすることになる。
へえ。
ASCIIコードで32はスペース、33は!、34は"、35は#。
つまりわかりやすく書けば、
if (argc % 2 == 0) {
putchar(d++ == 0 ? '"' : '!');
}
else {
putchar(d++ == 0 ? '#' : ' ');
}
となる。
更にわかりやすくなるように書き換えていって、結局はこんな感じに書いてみた。
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char** argv) {
int n,d,l = 0;
char* str = "@NKA"
"CLCCGZAAQBEAADAFaISADJABBA^"
"SNLGAQABDAXIMBAACTBATAHDBAN"
"ZcEMMCCCCAAhEIJFAEAAABAfHJE"
"TBdFLDAANEfDNBPHdBcBBBEA_AL"
" H E L L O, W O R L D! ";
for (d=atoi(argv[1])/10*80 - atoi(argv[2])/5 - 596; (n=str[l]); l++) {
for (;n>64;n--) {
if (l % 2 == 0) {
putchar(d == 0 ? '"' : '!');
}
else {
putchar(d == 0 ? '#' : ' ');
}
d++;
}
}
return 0;
}
@NKA…で始まるデータはもちろん地図情報。@(ASCIIで64)が0、A(ASCIIで65)が1、B(ASCIIで66)が2、…という意味がある。
それぞれの数字には、陸地あるいは海のデータが横に何個連続しているのか、という意味がある。
奇数番目は陸地のデータ、偶数番目は海のデータ。
つまり、1文字目(@)は最初に陸地のデータが何個連続しているのか(この場合はゼロ。つまり左上は海から始まることになる)、2文字目(N)はその次に海のデータが何個連続しているか、3文字目(K)がまた陸地で、…というデータになっている。
興味深いのは最後の" H E L L O, W O R L D! "の部分。スペース(ASCIIで32)は@(ASCIIで64)よりも小さいので、陸地はなし。次のH(ASCIIで72)は海が8個、次が陸地はなしで、また海があって、…ということで結局海が続いていることになる。
海を書いているのか、あるいは陸地を書いているのか、のフラグの変数がl(あるいはargc)。
また、1文字書くごとにdの値が増えていって、0になった時だけ普通の海(スペース)の代わりに「#」、陸地「!」の代わりに「"」が出力される。
マジックナンバーの596は北緯0度・東経0度の場所を意味している。つまり596番目の文字が基準点となっている。
ふーむ。ほんとによく書いてあるねえ。すごいねえ。