ref: http://ioccc.org/2015/endoh1/prog.c
#define/**/Alan/**/(fflush(0),j=c=0;++c<b[6]+7;v=b[c]^(b[c+ char*H="close\r\nContent-Type:text/html\r\n\r\n<canvas id=\ 'c'width='128'height='128'style='width:256px;height:256px'\ ><script>x=y=-1;v=window.c;v.onmousemove=function(e){x=e.p\ ageX-v.offsetLeft;y=e. pageY-v.offsetTop};w=\ new WebSocket('ws'+ location.href.subs\ tr(4));w.binary" "Type='arraybuff\ er';w.onmess" "age=function(\ e){c=v.getC" "ontext('2d')\ ;b=c.crea" "teI" "mageData(12\ 8,128);u= new Uint8Array(d=e. data);b.dat\ a.set(u) ;c.putImageData(b,0,0) ;u[0]=x/2;\ u[1]=y/2 ;w.send(d.slice(0,x<0?0: 2));x=y=-\ 1}</scr" "ipt>",b[9999];float*e,d[ 65536],u,v ,lu,lv, z;void*f;typedef unsigned long long l;l*p,t[ 99]={0x67452301,0xEFCDAB89, 0x98BADCFE ,308438* 881,3285377520 },i,j,k ,n,m[204]; #include /*io*/ <stdio.h> /*turing*/ void s(){ ; for( k =0;k++<7 * 2 *9;)for(i= 0;++i<127; ) e=d + i* 4 +512*k,1[e] +=(i-u)*(i -u)+(k-v)* (k- v )<20?*e+=UV_DROP:0;}l*q= m, g=1LL<<32; l(h)(l v,l (a)){ return(v<<a)|(v%g>>(32-a ) );}int main (int c/*ha r*/, char**y){for(e=d;fgets(b ,m[97]=480,\ stdin)&&*b >31; )for( i=j=0;n=b[i],i<18 ? (l)"sec-webs\ ocket-key: "[i] ==(n|32):n-32? m[j/4] |=(j< 24?n:(l) "258EAFA5-" "E914-47DA-95CA-C5AB0DC85B" "11\x80"[j-24]) <<(3-j%4)*8 ,++j<61:1;)i++;for(j=3;--j; ){for(i=4;++i<74 ;)i>9?p=q+i- 2 ,p[8]=h(p[5 ]^*p^p[-6]^p[-8] #define/*hah aha <--mouth*/ laplacian(u)l##u ,1):(t[i]=t[9 -i] );for(p=t+7 ,i=-1;++i<82;k =*p++,p[2]=h(p[1],5) +p[-3]+n+ (i/+ 20%2?*p^k^p[- 2]:(*p&k)|((i< 20?~*p:*p|k)&p [-2 ]))+*q++,t[+ 81-i]+=(i>76)* (* p= h(* p,30*(i<80) )))for(;n-k;n=((( 1LL +(9<<i/20 )/8)<<60)/k+k)/2) k=n ;} for (i =0;i<57; i++)i<30?q[i%5* 16/ 3+ i/5] |=t[i%5]%g<<4 >>(30+i%5%3*2-i/5 *6)& 63,0 :(n =*q++,b[i-30]= n<62?n-37+"fl!" [n /26]:n *4- 205);for(prin\ tf("HTTP/1.1 "/* | */"%d " "OK\r\nConnecti\ on:%s%.27s=\r\n\r\n" ,101 +99*! *m,!*m?H:"upgrade\ \r\nUpgrade:webso" "c" "ket\r\nSec-WebSocket-Acce\ pt:",b);e-d<65536 ; e+= 4)e[1]=(*e=UV_BACKGROUND);for (;*m;c=0){for(f= c< 2 ?0:fopen(y[1],"r");f&&fscanf(f, "%f,%f,",&u,&v)>0;)s ();for(;j<SPEED*4;j+=2)for(i=0;i< 63504;e+=5-j%4*2,z= TIMESTEP,*e=u+z*(elta_u),e[1]=v+z* (elta_v),i+=4)for(c= 0;c+2;u=v,v=e[4],lu=lv,lv=e[-508]+*e+ e[8]+e[516]-v*4)e=d+i+512+i/504*8+j%4-c--;for(;n=c%4,65544> c;c++)putchar(c>7?n>2||(u=d[c-n-7]*4*(n<2?!n?RGB))>255?255: #define/*x*/Turing(x)4]=getchar()&127))u=v;if(b[6]>1)s();}} u<0?0:u:c<0?124-c*3:c==5);/* -- The word "genius" is */ for Alan Turing (1912--1954)
アラン・チューリングの肖像家風のプログラムです。
ビルドはちょっと難しい。
$ clang -O3 -std=c99 \ -Wall -Wextra -pedantic -o prog prog.c \ -Delta_u="Du*laplacian(u)-u*v*v+F*(1-u)" \ -Delta_v="Dv*laplacian(v)+u*v*v-v*(F+K)" \ -DF=0.040 -DK=0.060 -DDu=0.200 -DDv=0.100 \ -DUV_BACKGROUND=1,0 -DUV_DROP=-0.5,0.5 \ -DTIMESTEP=1.0 -DSPEED=2 -DRGB=255:128:192
これで出来た実行ファイルを tcpserver コマンドの上で実行します。tcpserver は inetd の簡易版みたいなコマンドで、ソケットを待ち受けて accept したら引数のコマンドを実行してくれる DJB 謹製ツール*1です。
$ tcpserver 10333 ./prog ioccc.txt
起動したら、HTML5 に対応している最近のウェブブラウザで http://localhost:10333/ に接続します。なんかモワーと動きます。
動画。
解説
アラン・チューリングは、一般的にはエニグマの暗号解読で知られ、計算機科学の分野ではチューリングマシン・チューリング完全などで圧倒的に有名ですが、実は他の分野にもいろいろすごい成果を残しています。統計の分野では中心極限定理を証明し(12 年前に証明済みだったけど独立に証明したらしい)、人工知能の分野ではチューリングテストの提案で名を残し、行列の LU 分解もチューリングの考案だそうです。
晩年の業績に反応拡散系というのがあります。これは、自律的にパターンが形成される現象を説明するための数理モデルです。複数種類の化学物質がシャーレなどの中に入れられたとき、物質同士が化学反応して別の物質に変わる「反応」や、単に物質が周りににじみ広がっていく「拡散」がおきます。反応や拡散の式次第で、しましまや斑点、迷路や唐草模様のようなパターンが発現することがあります。*2
ということで、このプログラムは反応拡散系をシミュレーションするプログラムです。反応拡散系のモデルにはいろいろな式があるので、ビルド時に具体的なモデルを指示できるようにしました。それがあの長大なビルドオプションで表現されてます。式を変えるといろいろ動きが変わります。詳しくは remarks を。
で、単に画像や動画を出力するのではつまらないので、WebSocket と HTML5 Canvas を使ってインタラクティブにしてみました。IOCCC のために JavaScript を書くという楽しみ。
戦略と狙い
近年の IOCCC の大作偏重傾向にあってるし、内容的にもハッカー魂をくすぐる系なので、まあ通ると思ってました。審査員の環境でうまく動かないことだけを心配してましたが、問題なかったようで何より。ただ、大作系に迎合してるので、個人的には底まで好みでもない。
製作のきっかけは水族館でノウサンゴを見かけたことです。どういう仕組みでこういう形になるんだろうとか言ってたら @hirekoke さんが反応拡散系を調べて教えてくれたので作ってみました。チューリングにからめたのは後付け。ちなみにチューリングの肖像画も例によって @hirekoke さんが描いてます。
反応拡散系はパラメータ設定がとても繊細で、論文のとおりに作ってるつもりでも再現しないのが大変でした。既存の反応拡散系シミュレータ Ready のパターンファイルを参考にしつつ、どうにかいくつか例を作った感じです。
IOCCC において X server 以外で GUI をポータブルに提供する方法を提案する、という狙いもあったのですが、WebSocket のネゴシエーションに SHA1 の計算が必要だと判明して、コンパクトに仕上げるのは無理でした。
他の賞についてはまた明日。待てない人は拙著でも読んでて下さい。