The 21st IOCCC: Most complex ASCII fluid のエントリ

ref: http://www.ioccc.org/2012/endoh1/endoh1.c
ref: http://www.ioccc.org/2012/endoh1/hint.html

#  include<stdio.h>//  .IOCCC                                         Fluid-  #
#  include <unistd.h>  //2012                                         _Sim!_  #
#  include<complex.h>  //||||                     ,____.              IOCCC-  #
#  define              h for(                     x=011;              2012/*  #
#  */-1>x              ++;)b[                     x]//-'              winner  #
#  define              f(p,e)                                         for(/*  #
#  */p=a;              e,p<r;                                        p+=5)//  #
#  define              z(e,i)                                        f(p,p/*  #
## */[i]=e)f(q,w=cabs  (d=*p-  *q)/2-     1)if(0  <(x=1-      w))p[i]+=w*/// ##
   double complex a [  97687]  ,*p,*q     ,*r=a,  w=0,d;    int x,y;char b/* ##
## */[6856]="\x1b[2J"  "\x1b"  "[1;1H     ", *o=  b, *t;   int main   (){/** ##
## */for(              ;0<(x=  getc (     stdin)  );)w=x  >10?32<     x?4[/* ##
## */*r++              =w,r]=  w+1,*r     =r[5]=  x==35,  r+=9:0      ,w-I/* ##
## */:(x=              w+2);;  for(;;     puts(o  ),o=b+  4){z(p      [1]*/* ##
## */9,2)              w;z(G,  3)(d*(     3-p[2]  -q[2])  *P+p[4      ]*V-/* ##
## */q[4]              *V)/p[  2];h=0     ;f(p,(  t=b+10  +(x=*p      *I)+/* ##
## */80*(              y=*p/2  ),*p+=p    [4]+=p  [3]/10  *!p[1])     )x=0/* ##
## */ <=x              &&x<79   &&0<=y&&y<23?1[1  [*t|=8   ,t]|=4,t+=80]=1/* ##
## */, *t              |=2:0;    h=" '`-.|//,\\"  "|\\_"    "\\/\x23\n"[x/** ##
## */%80-              9?x[b]      :16];;usleep(  12321)      ;}return 0;}/* ##
####                                                                       ####
###############################################################################
**###########################################################################*/

解説

流体力学シミュレータです。以下のように実行してみてください。

$ gcc -o endoh1 endoh1.c -DG=1 -DP=4 -DV=8 -D_BSD_SOURCE -lm
$ ./endoh1 < endoh1.c

忙しい人のためのデモ動画。

教科書的な粒子法 (SPH 法)です。粒子はそれぞれ位置と密度と速度を持っていて、ナビエ・ストークス方程式に従い、外力、圧力、粘性抵抗によって動きます。("-DG=1 -DP=4 -DV=8" は、それぞれの力の係数。変えれば流体の挙動が変わる)

標準入力は初期盤面として使います。'#' は壁粒子 (動かない粒子) 、それ以外の文字は動く粒子として扱います。

他にもいくつか盤面を用意してあります。

$ ./endoh1 < logo.txt
$ ./endoh1 < column.txt
$ ./endoh1 < pour-out.txt
$ ./endoh1 < tanada.txt

審査員や銀賞の @hamano さんが作ってくれた盤面も公開されてます。
さらに、粒子の密度を端末の 256 色で表示する endoh1_color.c も (入賞後に審査員に言われて) 作り足しました。

狙いと戦略

1 つめが趣味のエントリだったので、こっちは積極的に入賞を狙って行きました。
去年の winner をみて、shinh さんのピクロスソルバとかライフゲームの Garden of Eden 計算とか、普通に実装しようとしても難しいネタの受けがいいみたいなので、流体シミュレーションを選びました。というのは、妻であるところの @hirekoke さんが当時趣味で SPH 法を調べていて、教えてもらえたので。
実装自体は、1 つめの作品以上に普通です。強いて変わったところを挙げるなら、ベクトルを C99 feature の double complex 型で表現してるところ (ソースコード自身を初期盤面にするのは IOCCC では必然ですが、そのために C99 feature である一行コメント (//) が必要だったので、いっそ完全に C99 依存とした) ですが、複素数でベクトルを表すとかすごく普通だよね。
こっちも remark には力を入れました。1 つめの remark とフォーマットを変えてみたとか。その方が説明しやすかったというのもあるけれど、remark のフォーマットで明らかに同一人物のエントリだとわかると「どっちか落とそう」って心理が働きそうだなーとか。あとはロゴを入れたりとか、審査員にお茶を淹れてみたりとか。

流体シミュレーションというネタ選定にはわりと自信あったのですが、でも優勝できるネタではないですよね。ひねりがない。脇役にはなれても主役にはなれない感じ。その点、銅賞は賄賂だし、銀賞は出力が見栄えするし、金賞は形而上な感じだし。これぞ主役のオーラですよね。