こんにちは。yhara@NaClです。
再来月に迫ったRubyKaigi 2018 仙台では、久々にあのコンテストの開催が予定されています。そう、TRICKです。
TRICKは「超絶技巧 Ruby 意味不明コンテスト in RubyKaigi」は、簡単にいうと普通でないRubyプログラムのコンテストです。
普通でない、とはどういうことでしょうか?説明するよりも見てもらった方が早いと思うので、今日は過去のTRICKの入賞作品を振り返ってみます。きっと、あなたの知らないRubyの世界が広がっているはずです。
TRICKの第一回は2013年に開催されました。
銅賞はmameさんの作品で、実行すると/dev/dspを利用して音楽が再生されます(動画)。
eval$C=%q(at_exit{
open("/dev/dsp","wb"){|g|h=[0]*80
$><<"\s"*18+"eval$C=%q(#$C);S=%:"
(S<<m=58).lines{|l|s=[128]*n=20E2
t=0; h.map!{|v|d=?!==l[
t]?1 :(l[
t]== ?#)?
0*v= 6:03
(v<1 ?[]:
0..n -1).
each {|z|
s[z] +=2*
M.sin(($*[0] ||1)
.to_f*M.sin(y= 40*(z+m)*2**
(t/12E0)/463)+ y)*(v-z*d/n)};
t+=1;v-d};m+= n;g.flush<<(s.
pack"C*"); puts(l)}}};M=
Math);S=%:
Jesu, Joy of Man's Desiring
Johann Sebastian Bach
#
| #
| #
# # # #
| | | #
| | # #
# # # #
| | | #
| | # #
(後略)
長いので省略していますが、後ろの部分が楽譜データになっています。また実行すると自分自身を出力する、いわゆるQuineにもなっています。
銀賞はshinhさんの作品で、Rubyプログラムとして実行可能なポエムです。
begin with an easy program.
you should be able to write
a program unless for you,
program in ruby language is
too difficult. At the end
of your journey towards the
ultimate program; you must
be a part of a programming
language. You will end if
you != program
一見ただの文章に見えますが、正しいRubyプログラムになっており、rubyで実行してもエラーになりません(出力もありませんが)。
金賞はkinabaさんの作品で、ASCIIの印字可能文字を一度ずつ使ったワンライナです。
!@THEqQUICKbBROWNfFXjJMPSvVLAZYDGgkyz&[%r{\"}mosx,4>6]|?'while(putc 3_0-~$.+=9/2^5;)<18*7and:`#
実行すると、ASCIIの印字可能文字が一度ずつ、ASCIIコード順に出力されます。
!"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~
すべての文字を一回ずつ使うという意味で、Rubyにおけるパングラムと言えるでしょう。
TRICK 2013の入賞作品についてはRubyist Magagineにも記事があります。
TRICKの第二回は2015年に開催されました。
銅賞はmonaeさんの作品で、実行するとサイズを二倍にした似たようなプログラムが出力されます。
;; ;; ;; ;;
;; ;; ;; ;;
;;eval$s =%q[i=1#
eval(%q[ xxxxxxxx
xx xxxx xx xx xxxx xx
xx xxxx xx xx xxxx xx
xxxxxxxx xxxxxxxx
xxxxxxxx xxxxxxxx
xx xx xxxxxxxxxx xx xxxxxxxx
j, t, p=0,[?;]," ev al$s=%qx
[#$s]".split*"";i,j,t=i-j,i+j,(x
[b=?\s]*j.abs+t).map{|s|r=t.shix
ft ||b;r.gsub!(?;){p.slice!0}if $x
f| |=p>p=p.center(i*i+j*j,?;);r ,x
s=[s,r]if(i*j<0);(b*i.abs+s).ljx
ust(r.size).gsub(b){r[$`.size]|x
|b}}unti l$ f;puts(t)# xx xx
xxxxxxxx xx xxxxxxxxxx xx xx
xxxxxxxx xxxxxxxx
xxxxxxxx xxxxxxxx
xx xxxx xx xx xxxx xx
xx xxxx xx xx xxxx xx
xxxxxxxx x].gsub\
/x.*|\s/ ,"")#];;
;; ;; ;; ;;
;; ;; ;; ;;
その出力を再度実行するとサイズがさらに倍と、実行の度に大きくなっていきます。
銀賞はKeisuke Nakanoさんの作品で、コラッツ数列を出力するプログラムです。
%%%while eval '_=%%r%%(.)...\1=%%=~[%%%%,,,,,%%%s ?=]*%%%%%%#"]*%%%%3x+1?%%'.% %%",%*p(_||=eval($**%%%))
異常に読みづらいので、Ruby力に自信のある方はぜひ読解にチャレンジしてください。
金賞はふたたびkinabaさんの作品で、実行すると円周率が出力されます。それだけでなく、ソースコードにある秘密があるのですが、分かるでしょうか?
big, temp = Array 100000000**0x04e2
srand big
alias $curTerm $initTerm
Numeric
Interrupt
big += big
printout _pi_ finish if $never
init ||= big
$counter ||= 02
private
(後略)
実はソースコード中の「単語」(token)の長さを先頭から見ていくと、以下のように3.1415926...のようになっているのでした。
big
3,
1temp
4=
1Array
5100000000
9**
20x04e2
6TRICK 2015の入賞作品についてはRubyist Magagineにも記事があります。
さて、第三回となるTRICK 2018 FINALはただいま応募作品を募集中です。締切は今月末の3月31日です。Rubyにはまだまだ知られざる側面があるはずです。たくさんの応募をお待ちしております。
結果発表は5月のRubyKaigi 2018 仙台の会場にて行われ、私も審査員として登壇する予定です。お楽しみに!