[C][IOCCC] IOCCC 2015 落選作供養 (1): 自己言及的ハノイの塔

IOCCC では、勝者発表からソースコード公開までの間に、勝者間で相互レビューが行われます。つまりみんなより先に楽しめるという特典。見たところ、今年は例年以上にハイレベルです。4 つも通ったのはむしろ運が良かった。ちなみに、ソースコード公開は年内予定のようです。ただし審査員の都合(と、やる気)次第で、しばしば数カ月単位で遅れるので、気長に待ちましょう。

ついでに、8 つも送ったプログラムのうち、どれが落選したのかが確認できました。ということで、落選したプログラムたちを公開供養していきます。


1 つめは「自己言及的ハノイの塔」です。

   #include/*hanoi*/<stdio.h>
   /*hAnOiOcoIoCcChAnOiOcCc*/
   #define/**/Q(q)char*b=#q;q
   /*hAnOiOcoIoCcChAnOiOcCc*/
   Q(int(n)=+0;typedef/**/int

  (I);I(m);char*p;char(s)[3565
  ];I(i);void(F)(char*g){for(m
  =(p-s)%+33*2;*g;g++)32<*g?*p
  ++=*g:0;}I(a)[3];I(main)(I(j
  ),char**V){I(v)=16;I(x);p=s;
  for(n=(j>1&&*V?+n+44:n+1)%45
  ;3560>i;)*p++=++i%99?i>+3465

 ?35:32:0;for(p[2]=41,p[1]=47,*
 p=42;m<4;(a[i]-=20-j,m++))for(
 i=(n*16/15+v/2)/v*(m%2+1)%3,j=
 32-m*2,x=j*+56,v/=2;j+35>x/j;x
 ++)s[(x/j-j-a[i])*99+x%j+33*i+
 m]=+90;;for(p=s,i=1;90-*++p||4
 +--i;)if(*p==+90){F(i?i+2?"/*"
 "hAnOiOcC":"#defi""ne/*n":"#i"
 "nclu""de""/*");p+=5-m;F(i?+i+

2?"oIoCcChAnOiOcCc*/":"*/Q(q)ch"
"ar""""*b""=#q;q":"*h""anoi*/<s"
"tdio.h>");}F("Q(""int(n)=BB;ty"
"pe""de""f/**/");;for(p[-13]=48+
n%10,p[-14]=n>9?n/10+48:43;*++b-
5*21;);for(i=0;*b;32<*b?90==*p?*
p=*b++:0,p++:b++);for(*p=+47,p[1
]=42;+36>i;puts(s+99*i++))for(p=
s+i*99+98;33>*p&&p-s;)*p--=0;i=0
;i=i+i;;return(b="IOCCC--HANOI",
i+i+i+i+i+i);}/*ZZZZZZZZZZZZZZZZ
###############################################################################################*/)

コンパイル・実行します。

$ gcc -o prog prog.c
$ ./prog
 





  #include/*Z*hanoi*/<stdio.h>
  /*hAnOiOcCZoIoCcChAnOiOcCc*/
  #define/*nZ*/Q(q)char*b=#q;q
  /*hAnOiOcCZoIoCcChAnOiOcCc*/
  Q(int(n)=+1;typedef/**/int(I
  );I(m);char*p;char(s)[3565];
  I(i);void(F)(char*g){for(m=(

 p-s)%+33*2;*g;g++)32<*g?*p++=*
 g:0;}I(a)[3];I(main)(I(j),char
 **V){I(v)=16;I(x);p=s;for(n=(j
 >1&&*V?+n+44:n+1)%45;3560>i;)*
 p++=++i%99?i>+3465?35:32:0;for
 (p[2]=41,p[1]=47,*p=42;m<4;(a[
 i]-=20-j,m++))for(i=(n*16/15+v
 /2)/v*(m%2+1)%3,j=32-m*2,x=j*+
 56,v/=2;j+35>x/j;x++)s[(x/j-j-

a[i])*99+x%j+33*i+m]=+90;;for(p=
s,i=1;90-*++p||4+--i;)if(*p==+90
){F(i?i+2?"/*""hAnOiOcC":"#defi"
"ne/*n":"#i""nclu""de""/*");p+=5
-m;F(i?+i+2?"oIoCcChAnOiOcCc*/":
"*/Q(q)ch""ar""""*b""=#q;q":"*h"
"anoi*/<s""tdio.h>");}F("Q(""int                                     (n)=BB;ty""pe""de""f/**/")
;;for(p[-13]=48+n%10,p[-14]=n>9?                                     n/10+48:43;*++b-5*21;);for
(i=0;*b;32<*b?90==*p?*p=*b++:0,p                                     ++:b++);for(*p=+47,p[1]=42
;+36>i;puts(s+99*i++))for(p=s+i*                                     99+98;33>*p&&p-s;)*p--=0;i
=0;i=i+i;;return(b="IOCCC--HANOI                                     ",i+i+i+i+i+i);}/*ZZZZZZZZ
###############################################################################################*/)

ぼくの本を読んだ人なら、後はわかりますね。さて、何回実行すると元に戻るでしょうか。

戦略と狙い

一目で「あーこれは Yusuke Endoh だな」って思えるやつを作りました。まさか 8 つも投稿してるとは思わないだろうから、他のプログラムの目くらましになるだろうという戦略。

そういう意味では捨て石っぽい位置づけではありましたが、Omoikane さんのアニメキャラ枠のように Quine 枠も定番化するといいなあ、と淡い期待もありました。しかし儚く散りました。見た目はともかく内容が代わり映えしないのはさすがにダメですかね。それでも例年なら通っていたんじゃないかという気もしますが。

TLE 2015 のときに、マクロを使ってほとんど重複のない Quine を書く方法を shinh さんに教えてもらったので、さっそくそれを使ってみました(書籍 127 ページ参照)。46 段階くらい変形するのでコード中の各所にスペースや改行が割り込んでくるのですが、どこで区切られても問題ないようにプログラムを書きました。110 ページに書いてある通り(宣伝しつこい)、C 言語は意外と空白の挿入に強い言語なので、それほど難しいことではありません。


他のはまた明日。