『プログラミング Elixir』を読んで

プログラミングElixir
プログラミングElixir
posted with amazlet at 16.08.22
Dave Thomas
オーム社
売り上げランキング: 1,168

川崎 Ruby 会議 01 の会場で、訳者の笹田さん・鳥井さんから一冊献本いただきました!ありがとうございます!さっそく読み終えたので、紹介を書いてみます。

書評

Elixir に興味がある人がこの本を読むべきなのは、言うまでもないと思います。そういう人は、Elixir に詳しそうな人による書評(このへんとかこのへんとか)を見るといいと思います。

正直、自分はさほど Elixir に興味ないのですが、この本はとてもおもしろく読むことができました。なぜかというと、Ruby っぽいオレオレ言語を作りたい野望を漠然と持ってる人間には、非常に刺激的な内容だったからです。Elixir 自身が「Erlang VM の上で Ruby っぽい言語を作ったらどうなるか」というのを体現していて、「あーわかるわかる、Ruby ここ良くないよね」とか「うわー Erlang VM のつらみを継承してるなー」とか思いながら読んでたら、一日で読み終えてました。

Elixir 自身だけでなく、本書の構成や説明がどことなく「Ruby ファンの、Ruby ファンによる、Ruby ファンのための」という感じだったのも面白かったです。Erlang/Elixir というと、とにかく並列性の話を期待しますが、本書の第 I 部(2〜13 章)では並列性の話は全く出てきません。150 ページ以上かけて、Elixir 言語自体をじっくり説明します。しかし、退屈にならないように構成と説明が工夫されています。まずはパターンマッチ(2 章)と不変性(3 章)という Ruby にはない性質から始めて、それから言語全体を概観する(4 章)。それから関数の話をし、リストとからめて再帰まで説明する(5〜7 章)。その勢いで他のコレクションや文字列などデータ構造の話を流し(8〜11 章)、ここでいまさら制御フロー(12 章)。斬新な流れでした。ここで終わると、この後いざ何か書こうとしたときに砂漠の真ん中に放り出されたような気分になりそうですが、最後の 13 章で、GitHub の issues をフェッチして整形出力するちょっとしたアプリを題材に Elixir での開発フローのデモがあり、フォローも万全でした。

そうして Elixir という言語を一通り理解した上で、第 II 部はついに並列性の話です。が、ここはさらっと流されている感じでした。プロセスやノードの低レベル API の話(14〜15 章)と、高レベル API というか OTP という並列実行管理システムの話(16〜18 章)などでした。この辺は明らかに、これだけで本が数冊書けるレベルのものなんだろうなーというところはよく分かりました(そして自分が興味ないところなので、ここを飛ばすのは「いいぞもっとやれ」という感じ)。最後の第 III 部は、マクロやモジュールに駆け足で触れて終わり。

ということで、第 I 部が個人的には一番エキサイティングでした。Elixir に興味がなくても Ruby とオレオレ言語設計に興味がある人(誰?)は是非読むといいと思います。

(なお、関数型プログラミングに関する記述については、ちょっと怪しい雰囲気がありました。sum の再帰的構造が sum([head|tail]) = <> + sum(tail) とか。アキュムレータの説明をしたかったようですが。まあ、「この本で関数型プログラミングを勉強しよう」と思う人はいないと思うので大丈夫かと思います)

Elixir について

さて、以下は書籍ではなく Elixir 自体への感想となります。

上述の通り、良くも悪くも「Erlang VM の上で Ruby っぽい言語を作ったらどうなるか」という感じの言語でした。Erlang といえば「VM は最強だけど言語は残念」ということで有名なので、かなり使い易くなっていると言えるのではないでしょうか。(使い込んだわけではないので印象ですが)

さらに、Ruby の弱点を克服しているところも好印象でした。Ruby 最大の不足である(と自分が思っている)パターンマッチは、Erlang 由来でばっちり用意されています。ブロックがキーワード引数の構文糖であることはすばらしいアイデアだと思いましたし、構文木をいじれるマクロは良し悪しですが、これらを組み合わせることで if 文相当が自力で定義できるのは非常にポイント高いです(Ruby がメソッド呼び出し 1 個あたりブロック 1 個しか書けないのは、if 文的なのを自分で定義できないのでしばしば苦痛です)。地味ですが、独自拡張可能な %-記法(Elixir では ~-記法)も「わかってるなー」という感じでした。

ただまあ、enjoy programming 勢としては、Elixir を普段使いにしたいとは思いませんでした。並列性ごときのために、あらゆる値が不変(配列やハッシュがない)のは、無理です*1。文字列・バイナリ周りのややこしげな仕様は、Erlang VM を利用する宿命かなんかですかね。それから、関数型プログラミングのは多分不変性と相性がいいからかと思うのですが、それにしても「メッセージを順次処理する」という単純なループを表現するのに末尾再帰を使うのは、やや滑稽に感じました。*2

それから、並列性がウリというわりには、それに特化した言語機能はないですよね。プロセス起動の spawn_link などには専用の記法があってもよさそうな。また、並列プログラミングのヤバさ(デバッグやテストがしにくい)を軽減してくれるような言語機能もなさげなので、ちょっと期待外れ感もありました。Erlang 的にはこのへんは言語機能ではなく、OTP という超重厚システムが頑張ってくれるというスタンスなんでしょうが、どうせ新たに言語を作るなら、OTP で培われたノウハウを言語機能として取り込めばよかったのになー、と思いました。OTP をほとんど理解してない人間の印象ですが。

ということで、Erlang VM の利点も欠点も継承してるなーという感じの言語でした。表層言語は Erlang から大分幸せになってるようですが(そしてそれはかなり重要ですが)、やっぱりこれは本質的に Erlang なんだと思います。

出来合いの VM の上で言語を作ると、どうしてもこういう妥協の産物になるんですよね。かといってスクラッチから書くと完成しないんですが。という感じで、オレオレ言語を作りたい野望を刺激される本でした。ああ。

*1:その犠牲を払ってでも並列性を必要としている人がいるのはわかってますし、そういう人にはいいんだと思います。でも自分にはつらい。

*2:普通は OTP の handle_call とかを実装するだけで、実際にはループを実装することがほとんどない言語なのかもしれません。

川崎 Ruby 会議 01 で基調講演しました

8/20 (土) に、川崎教育文化会館で川崎 Ruby 会議 01 が行われました。恐れながら、基調講演なるものをさせて頂きました。

内容は、東京 Ruby 会議 05 で話した Optcarrot の完全版でした。基調講演というと「その会合や分野の基本方針を示す講演」ですが、Ruby 会議関係の基調講演で(Matz の発表以外で)そういう感じの発表を見たことがなかったので、単に好きなことを話しました。

東京 Ruby 会議 05 の方では細かい実装技法の話しかしなかったので、我ながら偉そうだなーと思いながらも「最適化についての心構え」なるものを語ってみました。こんな感じ。

  1. 目標値を決めろ:最適化とはコードを汚すことなので、どこまで汚すかを事前に決めるべき。
  2. ボトルネックをいじれ:ボトルネック以外をいじるな。(ボトルネックを特定しないのは論外)
  3. アルゴリズム最適化を考えよ:メソッド展開とか汚い最適化は割に合わない。
  4. 効果を検証せよ:実行平均時間の単純比較ではなく統計的検定とか使うといい。有意差がなかったら変更を捨てろ。

2 と 3 はよく聞く話ですが、1 と 4 は一応自分のオリジナルです(同じこと言ってる人はいそうですが)。あと具体的なプロファイリングの方法とかを簡単に紹介しました。

川崎 Ruby 会議 01 の発表は、正直思っていたのの数倍以上に面白かったです*1。「Ruby の話をしたら負け」というカラーで、普通の RubyKaigi に飽き気味の人にはよかったと思います*2。運営チームの皆さん、ありがとうございました。次があったらまた参加します。

*1:面白さゼロという意味ではない。

*2:普通に Ruby の話が聞きたい人には微妙かもしれませんが、まあ川崎なら近隣の地域 Ruby 会議に行くのも難しくないので。逆に、他の地域 Ruby 会議にマンネリ感を覚えている人は特に来るといいのではないでしょうか。

[C][IOCCC] The 24th IOCCC: Best One-liner

f(y,x){int m,z;for(m=z=1;m*m<=y?z=y%m?z:m:x+1?z<2?x?f(x,0):putchar(64):f(z,x),putchar(x?10:32),y-=z:(f(z,y/z),0);)m++;}main(y){f(y-1,-1);}

実行します。

$ gcc -o prog prog.c

$ ./prog @
@ 

$ ./prog @ @
@ @ 

$ ./prog @ @ @
@ @ @ 

$ ./prog @ @ @ @
@ @ 
@ @ 

$ ./prog @ @ @ @ @
@ @ @ @ @ 

$ ./prog @ @ @ @ @ @
@ @ @ 
@ @ @ 

$ ./prog @ @ @ @ @ @ @
@ @ @ @ @ @ @ 

$ ./prog @ @ @ @ @ @ @ @
@ @  @ @  
@ @  @ @  

$ ./prog @ @ @ @ @ @ @ @ @
@ @ @ 
@ @ @ 
@ @ @ 

$ ./prog @ @ @ @ @ @ @ @ @ @
@ @ @ @ @ 
@ @ @ @ @

以上。

戦略と狙い

Animated Factorization Diagrams をイメージして作ってみました。

正直、これが通ったのは予想外でした。ワンライナーで大切なのは「こんな複雑そうなものがたったこれだけで!」というインパクトだと思うのですが、因数分解なんかはいかにも短く書けそうなネタなので、インパクト弱いなーと思ってました。しかも因数分解だけで 140 文字ぎりぎりになってしまうというゴルフ力のなさにがっかりした。でも解析したくなる程度の複雑さなのが逆によかったのかもしれない。

まとめ

ということで、IOCCC に入賞した endoh の 4 プログラム紹介でした。今回は本当にレベル高かったので、ぜひ他のプログラムも見てみてください。

[C][IOCCC] The 24th IOCCC: Back to the Future Award


  #include   /*recall-the\    /-good--old-\    /IOCCC-days!\    */<unistd.h>
   typedef  unsigned/*int*/  short U;U(main)  [32768],n,r[8];  __attribute__((
  # define  R(x)       A(r[  7-(n       >>x&  7)],       (n>>  x>>3       )%8)
  #define   C(x)       (U*)  ((/*             |IO|             -dpd
  */char*)  main       +(x)  )/*|             |CC|             ll*/
  # define  A(v,       i)(i  ?i<2             ?C(v             ):i\
  -4?v+=2,  C(i-       6?v-  2:v+       *C(v  -2))       :C(v  -=2)       :&v)
  /*lian*/  constructor))U(  x)(){for(;;*r+=  2,*r+=!n?_exit(  write(2,"Illeg"
  "al ins"   "truction ;-"    "(\n",24)),0:     n>>8==001?(      signed char




                 )n*2   :548==n>>    6&&usleep     /**/(10
                 )+n%  64==   4?0*  write  (r[7   /**/],C(
                 *C(*  r)),   *C(*  r+2)   )+4:  /**/ n>>9
                 ==63   &&--r[7-n/   64%8]?n%+  /**/  64*-
                 2:0,         n>>6  ==47   ?*R( 0):n>>12==1?
                 *R(0  )=*R   (+6)  :n>>  12==+       14?*
                 R(0)   -=*R(2*3)    :0)n=*C(*        r);}

普通に実行してもエラーが出るだけです。

$ gcc -o prog prog.c
$ ./prog
Illegal instruction ;-(

さて、これはなんでしょうか。

ネタバレ紹介

このプログラムを理解するには、第一回 IOCCC の優勝作品を知っている必要があります。これです。

short main[] = {
        277, 04735, -4129, 25, 0, 477, 1019, 0xbef, 0, 12800,
        -113, 21119, 0x52d7, -1006, -7151, 0, 0x4bc, 020004,
        14880, 10541, 2056, 04010, 4548, 3044, -6716, 0x9,
        4407, 6, 5568, 1, -30460, 0, 0x9, 5570, 512, -30419,
        0x7e82, 0760, 6, 0, 4, 02400, 15, 0, 4, 1280, 4, 0,
        4, 0, 0, 0, 0x8, 0, 4, 0, ',', 0, 12, 0, 4, 0, '#',
        0, 020, 0, 4, 0, 30, 0, 026, 0, 0x6176, 120, 25712,
        'p', 072163, 'r', 29303, 29801, 'e'
};
http://ioccc.org/1984/mullender/mullender.c

有名なので知っている人も多いかと思います。main が配列になっている素敵なプログラムです。つまり、機械語を直接、数字の配列として定義しています。C 言語の関数ってのは、実装上は機械語の先頭アドレスに対応するシンボルに過ぎないので、こういうことも可能なのです。

ぜひ動かしてみたいと思いますが、この機械語PDP-11 とかいう 1980 年ごろのマシンで動くので、残念ながら現代では動かせません。*1

そこで冒頭に示したプログラムが使えます。PDP-11 の「なんちゃって」エミュレータです *2 。以下のように実行してください。

$ wget http://ioccc.org/2015/endoh3/prog.c
$ wget http://ioccc.org/1984/mullender/mullender.c
$ clang -o mullender prog.c mullender.c
$ ./mullender

伝説の mullender.c が動きます。やったね。

このプログラムは GCC 拡張の __attribute__( (constructor) ) を使って、main より先に実行をフックします。その中で main 配列の要素を読み出し、PDP-11 のエミュレーションを行う、という仕組みです。

なお、PDP-11 の全命令はサポートしていません。というか、mullender.c が使っている 6 種類の命令しかサポートしてません。なので「なんちゃって」エミュレータ

戦略と狙い

IOCCC の Rule 1 、「あなたの作品は完全なプログラムでなければならない」に挑戦するというテーマで作りました。過去作品の mullender.c にべったり依存しているので、これは完全なプログラムと言えるのかどうか。しかも mullender.c が使っている命令しかサポートしていないので、他のものはとても動かせない。どやー。

と思って作ったのですが、よく見たら SOB という命令があったのでした。これは 1 引いて非ゼロだったら(後ろ方向限定で)ジャンプするという命令なんですが、実はこの一種類の命令だけでチューリング完全になるというたいへん強力な命令です。なので、やってみたらBrainfuckエンコードできてしまいました。まあそれはそれでむしろ面白いので、円周率計算とコッホ曲線のプログラムを PDP-11 のマシン語で書いて、おまけとしてつけました。

当初のテーマが達成できたかどうかは微妙ですが、いろんな意味で IOCCC ならではのプログラムになったと思います。過去に類のないプログラムなんで一抹の不安はありましたが、今大会 2 位のポジションにつけたようなのでまずまず。

*1:PDP エミュレータを使えば動かせるんだろうけど、よくわからないのでやったことはありません。

*2:コード中に ll-dpd とか書いてあります。逆さまに読めば pdp-11 。

[C][IOCCC] The 24th IOCCC: Most Overlooked Obfuscation

衝撃的な問題作。まずはこの動画をご覧ください。あなたの常識が崩れるはず。

何の呪いでしょうか。

自分で試してみたい人のコピペ用。

wget http://ioccc.org/2015/endoh2/prog.c
cat prog.c
gcc -w -o prog prog.c
./prog

ネタバレ解説

バックスペース文字の悪用です。コードを 20 文字程度書き、そこからバックスペース文字でカーソルを左に戻し、また 20 文字程度コードを書く、というのを繰り返す感じのプログラムになっています。バックスペースは普通の ASCII 文字なので、valid な C 言語プログラムが含んでいいのです。

こういうネタは初期の IOCCC でいかにも既出な気がしたので全チェックしたんですが、意外にも見つからなかったので出しました。賞名のとおり、「見逃されていた難読化」ですね。

ちなみに動画の最後でもデモしてますが、less で prog.c を見ると Hello, world! に下線が表示されます。

$ less prog.c

タイプライタ・プリンタ時代に使われていた、overstrike(重ね打ち)と言われる技法のなごりが less に実装されているためです。詳しくは拙著『あなたの知らない超絶技巧プログラミングの世界』の付録 263 ページには載っていますので、よければどうぞ。(宣伝)

戦略と狙い

超絶技巧プログラミング本の付録には、ASCII コード表が載っています。なぜかというと、子供のころ N88-BASIC のユーザマニュアルの付録に載っていた ASCII コード表が大好きだったので、本を書くことになったとき、ASCII コード表は絶対載せたい!と思ったからです。

でまあ載せたのですが、せっかくだから、超絶技巧プログラミングで使えそうな制御文字について補足を書こうと思いました。そのとき、だいぶ前に man が強調文字を overstrike で書いてることを思い出したんです。なのでバックスペースについて書きました。

そのときは overstrike をネタにすることしか考えていなかったんですが、IOCCC 向けにネタを考えたとき、バックスペース自体がおもしろいと気づきました。それにフォーカスして作ったのがこれです。

もともと最初作ったのは、「"Hello, world!" と書かれているけど実行すると "Good-bye, world!" と出るプログラム」だったんですが、最近の IOCCC は一発ネタの通りにくいので、ひよって Quine にしておきました。完全純粋一発ネタの垂直方向ツーライナーがあえなく落選したことを考えると、正しい判断だったと思います。

[C][IOCCC] The 24th IOCCC: Most Diffused Reaction

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 の計算が必要だと判明して、コンパクトに仕上げるのは無理でした。

他の賞についてはまた明日。待てない人は拙著でも読んでて下さい。

*1:ちなみに DJBIOCCC 1991 の優勝者です。

*2:専門でもなんでもないので間違ってたらすみません。

[C][IOCCC] The 24th IOCCC の結果が公開されました

C 言語のプログラムの汚さで競い合うプログラミングコンテスト、The 24th International Obfuscated C Code Contest (IOCCC 2015) のソースコードいまごろになって公開されました。

ref: http://www.ioccc.org/years.html#2015

既報の通り、自分は以下の 4 つの賞を貰いました。

順に紹介していきます。