Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Upcoming SlideShare
Loading in...5
×
 

Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)

on

  • 44,541 views

内容は後で修正して再アップロードするかもしれません

内容は後で修正して再アップロードするかもしれません

Statistics

Views

Total Views
44,541
Views on SlideShare
42,755
Embed Views
1,786

Actions

Likes
69
Downloads
129
Comments
4

26 Embeds 1,786

http://aomoriringo.hateblo.jp 759
http://chezou.wordpress.com 437
https://twitter.com 198
http://macmini 110
https://si0.twimg.com 73
http://d.hatena.ne.jp 47
http://omega014.tumblr.com 38
https://twimg0-a.akamaihd.net 33
http://s.deeeki.com 24
https://cybozulive.com 11
http://tweetedtimes.com 11
http://ss.dotbranch.com 8
http://twitter.com 6
http://a0.twimg.com 5
http://feedly.com 4
http://nuevospowerpoints.blogspot.com.es 3
http://www.feedspot.com 3
http://www.hanrss.com 3
http://localhost 2
http://sc.dotbranch.com 2
http://pinterest.com 2
http://b.hatena.ne.jp 2
http://safe.tumblr.com 2
http://webcache.googleusercontent.com 1
http://nuevospowerpoints.blogspot.com 1
http://nuevospowerpoints.blogspot.mx 1
More...

Accessibility

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

14 of 4 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

    Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012) Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012) Presentation Transcript

    • Ruby による超絶技巧プログラミング 遠藤侑介
    • 宣伝: 翻訳本買ってください抽象によるソフトウェア設計(Daniel Jackson 著) – 中島震 監訳 ・ 今井健男・酒井政裕・遠藤侑介・片岡欣夫 共訳 (オーム社) – 会場で買えます! Types and Programming Languages (通称 TAPL) – Benjamin C. Pierce 著 – 絶賛翻訳中! 2
    • 目次• 背景: 近年のプログラミングの問題• 提案: 超絶技巧プログラミング• 実践 テーマ1: self-descriptive な Ruby プログラム テーマ2: 文字を制限された Ruby プログラム• まとめ 3
    • 近年のプログラミングの問題• 俗世の欲にまみれすぎ – 例: プログラミング言語 Ruby の宣伝文句 生産性が10倍! 10分でblogが 作れる! プログラミングが 楽しくなる!実用性なんか無くてもプログラミングは楽しい! ※個人の感想です 4
    • 提案: 超絶技巧プログラミング• 実用性を無視して美しいプログラムを書く行為 – 普通のプログラミング  puts “Hello, world!” – 超絶技巧プログラミング  alias|send¥ ;$stdin=GC | "%p?"%def# FALSE.gets();(8 | 64).chr+232424. to_s(25)+", "+%w|w ! | *"orlc". next<<012|| (c).Yusuke end;"oh, 2009" | "stegano-X."[0,4].reversed,be="whydoes","crypto";:make. | %.mains..treams,be.delete(d)• 由来: 超絶技巧練習曲 Transcendental Études (Liszt [1826]) – Transcendental: 「肉体・精神・魂のすべてを超越する」 http://ja.wikipedia.org/wiki/超絶技巧練習曲 5
    • 超絶技巧プログラミングの実践テーマ 1: self-descriptive な Ruby プログラムテーマ 2: 文字を制限した Ruby プログラム 6
    • 例題: FizzBuzz • 数字を 1 から順に出力する、ただし – 3 で割り切れる場合は "Fizz" – 5 で割り切れる場合は "Buzz" – 両方で割り切れる場合は "FizzBuzz" を出力する • 普通の Ruby プログラミングで FizzBuzz n = 1 while true case when n % 15 == 0 then puts "FizzBuzz" when n % 3 == 0 then puts "Fizz" when n % 5 == 0 then puts "Buzz" else puts n end n += 1 end 7
    • self-descriptive FizzBuzz eval(s=s= %w@proc{| n|z=32.ch r;k="[#{n +=1}]";u= ":>==;<==?"[m=n**4 %-15,m+13]||"#{$f= k}";d="Y.E.#{c=64. chr}*)";$f||d<<z +k;t="eval(s=s=%w# {c+s=s[0, 334]}#$f# ";25.time s{|y|m=u. bytes.map {|v|t<<s; (0..[62-v ,2].min). map{|x|"i f0zgl11p0 zghuhku744d8hzeg41qtfx7xs7t wflr".to_i(36)[x+32+v*3-y/5 *44]<1?z*9:t.slice!(0,9)}<< z}.join.rstrip;y>23&&m[-9,9 ]=d;puts(m)}}[1]#pY.E.@*) 8
    • self-descriptive FizzBuzz の実装 1. ソースコード自身を文字列として得る 1. 自己複製 2. 自分自身を次の数字の形に整形する 2. フォント埋め込み 3. 以上を「実行可能なアスキーアート」として書く 3. 実行可能なアスキーアート 9
    • 1. 自己複製• Quine 、自己出力プログラム、Print Me! とも• ふつうの自己複製プログラム eval s=“ s = ‘eval s=‘ + s.inspect; puts(s) “ ※改行は分かりやすさのために入れています ※inspect: 文字列の前後に “ “ をつけるメソッド• self-descriptive FizzBuzz でも同じ構造 10
    • 2. フォント圧縮• 元データ (横 3 × 縦 5 × 約 15 文字 = 210 バイト) ### # ### ### # # ### ### ### ### ### ### ## # # ## # # # # # # # # # # # # # # # # # ## # # # # ### ### ### ### ### # ### ### ### ## # # # # # # # # # # # # # # # # # # # # # # # ### ### ### ### # ### ### # ### ### # ## ## ## #• # を 1、空白を 0 にして二進数に 111 010 111 111 101 111 111 111 111 111 111 110 000 00 0 101 110 001 001 101 100 100 101 101 101 100 101 101 11 1 101 010 111 111 111 111 111 001 111 111 111 110 101 01 0 101 010 100 001 001 001 101 010 101 001 100 101 101 10 1 111 111 111 111 001 111 111 010 111 111 100 110 011 11 1• 10 進表示に (64 バイト) 1516849080105099949603183465996815374383250973658966149057739167• to_s(36) で36進数に (41 バイト) 8hlduayacv7bl0a0h2m2d2ti20qewh0rrsjcmsgpr 11
    • 3. 実行可能なアスキーアート1. コード全体を %w( と ).join で囲む – %w(...) は文字列の配列のリテラル %w(foo bar)  [“foo”, “bar”] – .join は配列を文字列として連結するメソッド [“foo”, “bar”].join  “foobar”2. eval する eval %w( pu ts3. 自由に整形できる! puts “Hi” “H i” ).join## 12
    • 以上の技法に基づいた他作品 13
    • Qlobe: self-descriptive 地球儀プログラム v=0000;eval$s=%q~d=%!^Lcf<LK8, _@7gj*LJ=c5nM)Tp1g0%Xv.,S[<>YoP 4ZojjV)O>qIH1/n[|2yE[>:ieC "%.#% :::##" 97N-A&Kj_K_><wS5rtWk@*a+Y5 yH?b[F^e7C/56j|pmRe+:)B "##% ::##########" O98(Zh)Iof*nm.,$C5Nyt= PPu01Avw^<IiQ=5$D-y? "##: ###############" g6`YT+qLw9k^ch|K),tc 6ygIL8xI#LNz3v}T=4W "# #. .####:#######" lL27FZ0ij)7TQCI)P7u }RT5-iJbbG5P-DHB<. " ##### # :############" R,YvZ_rnv6ky-G+4U $*are@b4U351Q-ug5 " #######################" 00x8RR%`Om7VDp4M5 PFixrPvl&<p[]1IJ " ############:#### %#####" EGgDt8Lm#;bc4zS^ y]0`_PstfUxOC(q " .#############:##% .## ." /,}.YOIFj(k&q_V zcaAi?]^lCVYp!; " %% .################. #. " ;s="v=%04o;ev"% (;v=(v-($*+[45, ":####: :##############% : " ])[n=0].to_i;)% 360)+"al$s=%q#{ "%######. ######### " ;;"%c"%126+$s<< 126}";d.gsub!(/ "##########. #######% " |¥s|".*"/,"");; require"zlib"|| "########### :######. " ;d=d.unpack"C*" d.map{|c|n=(n|| ":#########: .######: . " )*90+(c-2)%91}; e=["%x"%n].pack " :#######% :###### #: " &&"H*";e=Zlib:: Inflate.inflate( " ######% .####% :: " &&e).unpack("b*" )[0];22.times{|y| " ####% %### " ;w=(Math.sqrt(1-( (y*2.0-21)/22)**(; " .###: .#% " ;2))*23).floor;(w* 2-1).times{|x|u=(e+ " %## " )[y*z=360,z]*2;u=u[ 90*x/w+v+90,90/w];s[( " #. " ;y*80)+120-w+x]=(""<< 32<<".:%#")[4*u.count(( " . " ;"0"))/u.size]}};;puts¥ s+";_ The Qlobe#{" "*18+ ( "# :#######" ;"Copyright(C).Yusuke End¥ oh, 2010")}";exit~;_ The Qlobe Copyright(C).Yusuke Endoh, 2010 14
    • Qlobe の実装1. 自己複製する2. 地球儀をレンダリングして出力する – 世界地図が zlib 圧縮で埋め込まれてます3. 邪魔な地球儀はショートカット演算子などで回避 “zlib” || “地球部分"  “zlib” “地球部分” && “H*”  “H*” 15
    • 山手Quine t="+,m-n./mAm0o1p23a4q56r7sBt89u-t-1:v;A<w4x=y1z>[?]A^@CD_ z=27;eval$s=%w!c,s=["H+{K}8k->dXNpv-cD~@?(zhAi~>JOv<-;A(]oH+MFKs*+KOB825i$%QX9~P=HC{iIlj*Sh# CD_EsF`GHmIJbKa*l";eval$s=%w{F=%q{ceY8#<DvO1=x&t9CSOqMYkzH v=3U62LhUXhtnCx^{F=nuTtGG}@85_(xVvIWQ|Vllp[Gt22x&`^K3*ui;IW@O9-(`Z6V_T.E]%WHXYGa{O9A#msMgV{5 U.kCpz+Vo8hB.1AF&tq21+$/IrMY]U.aDd!-1y!4MMGQm6m?bYh($QMYpX R3XS/dxI8zM)XrbFom,$Msj8>=ca#i.yOqM-gtf2xH T#2VYW9Koq.)IjS:&n3f6$Q/@4-8m_[(HxaP>n*b]Ih/3`3T s4g,x1UlbNKH?>NzbisMn?sT@m3,F.Abb`xW!r%%Ybee>xkUfjf[(*^Nd uG-C~3Bn)d.PSdX8 uvtft?;j%bsM^v&h NcaFzv7)uyD=lkc+eYn5&dN/%.|o@pD|BPi+a`rJCgg>?AE; Xo_"@hQh%Fx*q[iB7EM"suSG8GVOIzceg/O=4CL,d[-k]twgVP`&wcfaT` W~){4l9}","_m?PM(N5L <,.ht}f8B|*o8|Qg?:v (@LY1^KvIm8twKZHvU@:&FS)r[N1?t9k26*=tiLQw<Tq$l 2M)j8sFY?(HKzOrVCHO_694[Uq8g @i/i;tMBG#;-;B]rV[])`3<os^. ]V1@Z3hnQ:cQb)>])-p }rU[8hN 7`j6SW r-ZW m2 3n<ZaJ %C%g @@+DABEERjKj5Yt~&>xL OV(SA<=ok%m[iV#qt[&dJ7SIdB;/ VUnVIrH;hEJ*QWD"E+5)gfrmD"#E ~8BN`L#u?tE+CH$wM%*J px[D;A t%sec waI. R; FIn( VUVq{0 6c Y]1EV sqNd_V1yp8"].map{| XlNVv1j)^^ bCi_gw+s-V s|n=0;s.unpack("C*") .map{| c|n=n* 91+( c-1)%9 2};n}; e= "z=#{z =($*[i=0]?(z+1):z- J<?fWdtbnxRgJm4J.yHO_ay2e%rc Tj]ALVU`V=]]W;x&9MP&g5zAVHR 1)%29};eval$s=%w"<<3 3<<$s[ 0,903] *3;1 4. time s{|y|b =" ";n=f= proc{|w|b<<e[i,w]; ?B,SZA+!_[0f!TUCv$Hin?-G7hAL BW6w1x+F#%@FZ<7!9;vNxsj6HW_O i+=w};t=s;f[4];z.dow nto(0){| a|a<1& &6.t imes {|x| y>1&&y<12&&c[n*60+y* Ao)H5cv`Ves-BQ"Z =K$_[o]Can(;1cJp 6-x-67]>0?(b<<32<<32):f[2]}while(0<n=(t/=38)%38)};f[4];y>12& &b[-28,28]=""<<33<<"*#..(c). HV<:4x2,AnZgqvsy >VWDZdF-+^ 46Z^Z@<>1< cJ3E4GYSqGg7$ocX Yusuke.Endoh.2010";puts(b)}#c,s=["H+{K}8k->dXNpv-cD~@? (zhAi~>JOv<-;A(]oH+MFKs*+KOB825i 88=*`RVO*WskDY-# uj$t3$XP#U IH]regXHa_ >sta`lbL+=J3sL3e $%QX9~P=HC{iIlj*Sh#v=3U62LhUXhtnCx^{F=nuTtGG}@85_(xVvIWQ|Vllp[Gt22x&`^K3*ui;IW@O9-(`Z6V_T.E] BYxm/a0]lV1?M4WA u7jCGk`UBzB#*gOJ %WHXYGa{O9A#msMgV{5R3XS/dxI8zM)XrbFom,$Msj8>=ca#i.yOqM-gtf2xHT#2!*#..(c).Yusuke.Endoh.2010 wHu#gQst^XB0VXjT imG<qb[s!* S#":,frD+N wn=nI<u;#dw*Y?"8 B#G[%YT$mvLd<gUd lN^6#bZX$S a#owd125V! 4d+zL5)I;JD-ToJ" uN?h9Braq+dG4Nr[ ynH,hS?nk4JD^/.q • 実行すると隣の駅名になる KS&kW@(62e]xb0j2(;4X[ROR2W Ifjf^3vhJ5jb5"sJ(4b6Ek1?Vx %s$^.yD.SY$:h[zd$D7o$n: Zp F= 2bHENRzBQhsd_7Im*HZG3xcx t#KdN4D3tEG%#F[1pbo_6C y;kI "Z`: ]^-/]HnWCrJ^=JBA9%gyIr %Xe,D&Lmb:S<o_(b4VJ ji*bc# G#ig: AQR[vp>>Jn;Mf$KRBf&7 [%X34447R.0v"Uz/4F "6Q+0>+1 N3OLCeMn ;8TQ>BHCW1";KrW,%P `C?@?)fz>c3B;r 8Q"QCjmU"3 SXd1Jt1qI; "G7HLO$I*6=fCC • 29 駅で元に戻る o!G6CSm1a] S(S#d#sa#2lXP& 4$L"^ir8_BEmkS vA!f@p!$A6 pE@#u%5QJda>[dT>cc4bYcAY)6uF 9%1C4f?GWDcZR`n,%>JrTqK$eHG2 W)B__.[JP+@2qlsWxug,O60@Nkj6VU#Gqp[fC%XOc`:C!-hbr3C0Dz2aLL RI%*4&LtoOJxHohC=*H#sc][4ZwId0O,R]s<]D#ykgKY7Oc1`heSG/Xxj LA2aiV!<Q;8G/!8>GlX^T4P-/.oIyvR>kPyJ;lXD1r8n5gHPeuA4%j8*0> Iu^>CRxHz3HYX*#n,t_EjxBRbgFH kj:PmmNq3MA10LXwbAW&S^/0_x,H 4d5"_9>K!n6*b(ij`:HQRKf]EJoM NwY>5Sid#5BuS8[sF`_[bf9Z<W vdK3HiV+1L.jL*%;&g.G#?S5:Xh$ /gWw#1U-lHTo"?_dxYHC&UGLa)yn %zdU1KPkrE wXsKbTBBix xh=#es7os:-9<`3Olf(!YN!hK?1a,2UMJ^`IC)oc8Z/TipLWy(%p0qUZoO ;W#bB%8=9CZvoU$eG;kXt[hewZnV!(B(u-[L3)l,6C%3.?u?znQyMgw31s [s4Ne+XNPNcpmuaJ<] Hd:/;va-yp4)mU.&Vr Z@*N3mTZX)0]%^]0d6 a@njg`2DJ;stf^WTr 3y%gWte5;+Q>ZbENlv rK!4M=y6IQ27&IJm>n w57+;)s=Foy<4pdw5i lSDhJRyao%_Wx+[lx6 D8Goea3uRPpunFulWq 0*3GoGaJyAHF$#bJca 5&Z0Kr[o,K*"/^jv6 m08,PTZy$g?eX[aN4j J]AkXcV72;!};f=0;F .unpack("C*").map{ |c|f=f*89+((c-2)%9 0-1)};requirezlib ;t=t.split*"";$*[0]?(t[/([* -K]+.)([*-K]+.)$/];t=$2+$`+s =$1):(s=t[/.+?[L-z]/];t=$+s );f=Zlib::Inflate.inflate(Ma rshal.dump(f)[7..-1] );S=%{ t="# {t}";eval$s=%w{#$s}* "";%|}+F*9;P=proc{pu ts(S.s lice!(0, 58));P};P[][][][s. upcase.unpack("C*" ).map{|c |c-=c>92?4 3:42;;P[][][20.t imes{|n|puts(("% 029b"%("¥0 "+f[60*c+3*n ,3]).unpack("N ")[0]).gsub( /./){$&<"1"? (S.slice!(0,2) ):(32.chr*2) })}]}][];puts(*["+"+"-"* 25,"|,##,(c),Yusuke,Endoh,20 09".split(",").join(32.chr)].map{|l|S.slice!(0,32)+l})}*"" ;%|ceY8#<DvO1=x&t9CSOqMYkzHU.kCpz+Vo8hB.1AF&tq21+$/IrMY]U. aDd!-1y!4MMGQm6m?bYh($QMYpXs4g,x1UlbNKH?>NzbisMn?sT@m3,F.A bb`xW!r%%Ybee>xkUfjf[(*^NdXo_"@+------------------------- hQh%Fx*q[iB7EM"suSG8GVOIzceg/O=4| ## (c) Yusuke Endoh 2009 16
    • 自己相似 Quine eval$s=%wk=0013;f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.ro eval$s=%wk=0026;f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.ro eval$s=%wk=0054;f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.ro eval$s=%wk=0067;f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.ro eval$s=%wk=0136;f=proc{|x,y,s|x*x+y* eval$s=%wk=0000;f= und,y.round;x.abs>21+s||y.abs>4+s||(x*x+(y*2+6)**2<4?f[x* y*4<36864&&(u,v=x.round,y.round;x.abs>21+ proc{|x,y,s|x*x+y*y*4<36864 96,y*96+288,s*192]:u*u<441&&v*v<25&&"36effv0qbzox5c3npa19 s||y.abs>4+s||(x*x+(y*2+6)**2<4?f[x*96,y*96+2 &&(u,v=x.round,y.round;x.abs>21 1hhgzrio5b3640nv9g9jzvnm8a67su".to_i(36)[u-v*41+143]>0))} 88,s*192]:u*u<441&&v*v<25&&"36effv0qbzox5c3npa1 +s||y.abs>4+s||(x*x+(y*2+6)**2<4?f[ ;k=(k+($*[0]||0).to_i)%99;t=("eval$s=%%w%ck=%04o;"%[39,k] 91hhgzrio5b3640nv9g9jzvnm8a67su".to_i(36)[u-v*41+14 x*96,y*96+288,s*192]:u*u<441&&v*v<25&&" ;k=(k+($* )<<($s[7,530]<<35<<35)*9;s=8/96**(1-k.to_f/98);o=(-11..11 3]>0))};k=(k+($*[0]||0).to_i)%99;t=("eval$s=%%w%ck=%0 36effv0qbzox5c3npa191hhgzrio5b3640nv9g9jz [0]||0).to_i)%99; ).map{|j|(-28..28).map{|i|f[i*s,j*s-36*(8-s)/95,s/4]??a:3 4o;"%[39,k])<<($s[7,530]<<35<<35)*9;s=8/96**(1-k.to_f/9 vnm8a67su".to_i(36)[u-v*41+143]>0))};k=(k+( t=("eval$s=%%w%ck=%04 2.chr}*""}*10.chr;o.sub!(/aaaa((#{"Quine";(s=92.chr)+?s}+ 8);o=(-11..11).map{|j|(-28..28).map{|i|f[i*s,j*s-36*(8- $*[0]||0).to_i)%99;t=("eval$s=%%w%ck=%04o;"%[ o;"%[39,k])<<($s[7,530]<< 2.chr}*"" a{1,3})*#{s+?s}*)#{s+?z}/){39.chr+%(*"")+$1.tr(?a,?;)};o. s)/95,s/4]??a:32.chr}*""}*10.chr;o.sub!(/aaaa((#{"Quine"; 39,k])<<($s[7,530]<<35<<35)*9;s=8/96**(1-k.to_f 35<<35)*9;s=8/96**(1-k.to_f }*10.chr;o.su gsub!(/a/){t.slice!(0,1)};puts(*o)##f=proc{|x,y,s|x*x+y*y (s=92.chr)+?s}+a{1,3})*#{s+?s}*)#{s+?z}/){39.chr+%(*"")+$ /98);o=(-11..11).map{|j|(-28..28).map{|i|f[i*s, /98);o=(-11..11).map{|j|(-2 b!(/aaaa((#{"Qu gsub!(/a/){ *4<36864& 1.tr(?a,?;)};o.gsub!(/a/){t.slice!(0,1)};puts(*o)##f=proc j*s-36*(8-s)/95,s/4] t.sli ??a:32.chr}*""}*10.c 8..28).map{|i|f[i*s,j*s-36*(8 ine";(s=92.chr)+? &(u ,v=x.roun ce!(0,1)};p d,y.round ;x.abs>2 s}+a{1,1 + 32.chr}*""}* {|x,y,s|x*x+y*y*4<36864&&(u,v=3})*#{s hr;o.sub!(/aaaa((#{" uts (*o";(s=92.chr)+?s}+a{1 -s)/95,s/4]?Quine x.round,y.round;x.abs>21+ ?a: s||y.abs> ) 4+s||(x*x +( 10.chr;o.sub!(/aaaa((#{"Quine s||y.abs>4+s||(x*x+(y*2+6)**2<4?f[x*96,y*96+288,s*192]:u* ,3})*#{s+?s}*)#{s+?z pro }/){39.chr+%(*"")+$1 ##f= y*2 +?s}*)#{s+?z}/){3 +6)**2<4? c f[x*96,y* 96 +y,s| ,sx*x+ 2]: u*u<441 &&v* v< 25&&"36ef u<441&&v*v<25&&"36effv0qbzox5c3npa191hhgzrio5b3640nv9g9jz .tr(?a,?;)};o.gsub!(/a/){t.slice!(0,1)};puts(*o {|x, ";(s=92.chr)+?s}+a{1,3})*#{ 288 9.chr+%(*"")+$1 *19 y*y* 4<36864&&(u ,v=x.rou n fv0qbzox5 c3 npa19 1hd;x. rio 5b3 640 nv9g9jz vnm8a67su vnm8a67su".to_i(36)[u-v*41+143]>0))};k=(k+($*[0]||0).to_i )##f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.round, d,y. rouns+?s}*)#{s+?z}/){39.chr+% .tr(?a,?;)}21+s||y.abs hgz abs> >4+s||(x *)%99;t=("eval$s=%%w%ck=%04o;"%[39,k])<<($s[7,530]<<35<< ".to_i(36 )[ +6)* 41*2<4 ;o. 0)) };k *96+28 8,s*19 2 x+ y.round;x.abs>21+s||y.abs>4+s||(x*x+(y*2+6)** (y*2 u-v* (*"")+$1.tr(?a,?;)};o.g=(k +14 ?f[x *96,y 3]> +($*[0]|| ]35)*9;s=8/96**(1-k.to_f/98);o=(-11..11).map{|j|(-28..28p 0).to_i)% 99;t=(" ev al$s=% %w% ck= %04 fv0qbz 9,k])<<($ :u 2<4?f[x*96,y*96+288,s*192]:u*u<441&&v*v<25& *u<4 41&&sub!(/a/){t.slice!(0, o;"%[3 ox5c3n v*v< 25&& "36ef a ).map{|i|f[i*s,j*s-36*(8-s)/95,s/4]??a:32.chr}*""}*10 s[7,530]< 191hhgz rio5 &"36effv0qbzox5c3npa191hhgzrio5b3640nv9g9 1)};puts(*o)##f b364 0nv9 g9jzv nm8a <35<<35)* 67su".to_ g i .chr;o.sub!(/aaaa((#{"Quine";(s=92.chr)+?s}+a{1,3}) 9;s=8/96**(1-k.to_f/98);o=(-11..11).map{|j|(-28..28).map{ (36)[u -v*4 jzvnm8a67su".to_i(36)[u-v*41+143]>0))}; ($*[ sub!(/a/){t.s1+14lice!(0,1)};p =pr 3]>0 ))};k =(k+ uts(*o)##f=pr o 0 |i|f[i*s,j*s-36*(8-s)/95,s/4]??a:32.chr}*""}*10.chr;o.sub *#{s+?s}*)#{s+?z}/){39.chr+%(*"")+$1.tr(?a,?;)};o ]||0). to_i c{|x,y,s|x*x+)%99y*y*4<36864&& k=(k+($*[0]||0).to_i)%99;t=("eval$s %w%c ;t=( "eval $s=% (u,v=x.round, y k=%04o;"%.round;x.abs> !(/aaaa((#{"Quine";(s=92.chr)+?s}+a{1,3})*#{s+?s}*)#{s+?z .gsub!(/a/){t.slice!(0,1)};puts(*o)##f=proc{| [39 ,k])<<($s[721+s||y.abs>4 =%%w%ck=%04o;"%[39,k])<<($s[7,5 +s||(x*x+(y*2 ,530 ]<<35 <<35 )*9;s=8/ + }/){39.chr+%(*"")+$1.tr(?a,?;)};o.gsub!(/a/){t.slice!(0,1 x,y,s|x*x+y*y*4<36864&&(u,v=x.round,y.round 6)**2<4?f[x*9 30]<<35<<35)*9;s=8/96**(1-k 192]:u*u<441& 6,y*96+288,s* oc{|x,y,s|x*x+y*y* .to_f/98);o=(-1*"" & 96**(1-k.to_f/98);o=(-11..11).map{|j|(-28..28).map{|i*"" )};puts(*o)##f=proc{|x,y,s|x*x+y*y*4<36864&&(u,v=x.ro*"" v*v<25&&"36ef ;x.abs>21+s||y.abs>4+s||(x*x+(y*2*"" 4<36864&&(u,v=x.r*"" fv0qbzox5c3np a191hhgz*"" ;;; 17
    • 15quzzle Quine でパネル移動後の盤面が出てくる eval$s=%w[b=0 x40e1359a76cb d8f2;i=(m=0.. 15).find{|i|1 >b&m=15<<4*i} ;t=m|n=m<<4*o =("AdABrBlBAu A"=~/(.)#{ARG V*}¥1/||04| |0)-4;(n<1||n >1<<64||[255< <12]&[t>>040| |___________2 |__________15 |___________8 |__________13 |0,t>>16,t]!= [])?t=0:i+=o; ;s="eval$s=%% w[b=0x%016x"% (b^=t.&b|m&b> >o*4)+$s.gsub (/(¥|_+¥d+)+/ ,)[/;.*/]+" ]*||0"<<92| |1;z=s=s.scan (/.{13}/);3.t imes{|j|s[(i| |__________11 |__________12 |___________6 |___________7 |0)/4*8+i+j*4 ,0]=m=(z=32.c hr)*13};c=b;4 .times{puts(( 0..3.times{pu ts((s.slice!( 0,4)*z).rstri p)}).map{j=c% 16;c/=16;;(0| |0)<(j)?"|"+j .to_s.rjust(1 2,"_"):m}*(z| |__________10 |___________9 |___________5 |___________3 |0),z)};b==0x fedcba9876543 21&&("%b"%"1t v7c1th0wylel7 3ba35knw3t".t o_i(36)).tr(" 01",".#").sca n(/.{25}/){pu ts$&}]*||0¥ |___________1 |__________14 |___________4 18
    • 関連研究• International Obfuscated C Code Contest (IOCCC) – みにくい C コードを書くコンテスト 円周率計算プログラム 電卓プログラム (hou [2011]) (westley [1988]) #include <stdio.h> #include <math.h>#define _ -F<00||--F-OO--; (略)int F=00,OO=00;main(){F_OO();printf("%1.3f¥n",4.*-F/OO/OO);}F_OO() int main(int argc,char** argv){{ if(argc<2){ _-_-_-_ puts( _-_-_-_-_-_-_-_-_ usage: calculator 11/26+222/31 _-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~calculator-¥ _-_-_-_-_-_-_-_-_-_-_-_-_-_ ! 7.584,367 ) _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ ! clear ! 0 ||l -x l tan I (/) |_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ ! 1 | 2 | 3 ||l 1/x l cos I (*) |_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ ! 4 | 5 | 6 ||l exp l sqrt I (+) | _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ _-_-_-_-_-_-_-_-_-_-_-_-_-_ ! 7 | 8 | 9 ||l sin l log I (-) | _-_-_-_-_-_-_-_-_-_-_-_ +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~(0 _-_-_-_-_-_-_-_ ); _-_-_-_ }} return 0; } 19
    • 超絶技巧プログラミングの実践テーマ 1: self-descriptive な Ruby プログラムテーマ 2: 文字を制限した Ruby プログラム 20
    • 使える文字を制限して Ruby を書く• 今日のテーマ: 小文字アルファベット(と空白)だけ• 実装方針 – 実行したいコードの文字列を構築し、eval する eval “code”• 説明の順序 1. アルファベット(大文字含む)+数字だけで書く (Hamaji [2008]) 2. 大文字を排除する 3. 数字を排除する 21
    • コード文字列を構築する• 問題: 文字列リテラルは使えない クォート使用不可 “code”• 解決: 文字列を返す組み込み関数を使う –例 String nil  “” – nilを文字列に型変換する:空文字列が得られる – 空文字列に ASCII code で文字を連結していく “”.concat(65)  “A” “A”.concat(66)  “AB” 22
    • ピリオドなしで concat を呼び出す ピリオド・カッコ• 問題: メソッドが呼び出せない 使用不可 “”.concat(65)• 解決: String のメソッドからはピリオドなしで呼べる – Ruby ではカッコは常に省略可能 class String 空文字列からコードを def generate 構築するメソッドを定義する concat 65 concat 66 新たな課題: end この構築メソッド自身を end どう呼び出すか? “”.generate 23
    • コード構築メソッドを起動する• Ruby の for 文 for 変数 in コレクション do ... end 構文糖 コレクション.each do |変数| ... end∴ コード構築メソッドを each という名前にすれば ピリオドなしで呼び出せる “”.each ≒ for elem in “” do end 24
    • 第一段階: アルファベットと数字で Ruby例: コード文字列 “p 1” を構築・ eval するコード class String def each 文字列を構成する様子 concat 112 “” concat 32 concat 112 concat 49 eval self “p” concat 32 exit end “p ” concat 49 end for i in “p 1” eval String nil do end 25
    • class String大文字を排除する def each ...• String の ”S” が 2 箇所 end end• class String の箇所 for i in – String クラスには定義できない String nil do end – トップレベルは Object クラス  トップレベルに定義すればよい public def each• String nil の箇所 clear – 文字列を返す別のメソッドにする ... – String#clear で空文字列に end for i in String nil do inspect do end 26
    • 第二段階: 小文字 alphabetと数字で Ruby例: “1” を出力するコード class String public def each def each concat 112 clear concat 32 concat 112 concat 49 concat 32 eval self concat 49 exit eval self end exit end end for i in for i in String nil do inspect do end end 27
    • 数字を排除する(1)• 欲しい数字の長さの文字列を作り size を呼ぶ – 例: 8 を生成するコード clear # “” concat size # “¥0” concat self # “¥0¥0” concat self # “¥0¥0¥0¥0” concat self # “¥0¥0¥0¥0¥0¥0¥0¥0” size # 23 = 8 が得られる• 今まで構築してきたコードが消えてしまう! 28
    • 数字を排除する(2)• 例外処理の構文 現在の self “...” begin A ensure B end – Java の try { A } finally { B } concat begin みたいなもの dup• 式全体が A の評価結果を返す ensure concat begin – A を評価し 65 を作る ensure – B を評価し clear end – B の評価結果を捨てて end A の評価結果を返す構文• 文字列の先頭に 1 文字追加 するイディオムが作れる “A...” 新しい self 29
    • loop do break public end catch inspect do def each loop do break clear end concat begin dup ensure clear concat concat concat concat size loop do break concat concat size end loop do break concat concat size end小文字アルファベットだけで Ruby を書く loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear concat concat concat concat concat concat size loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat concat size concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat size loop do break concat concat size end concat concat concat size loop do break public end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat concat concat concat size loop do break concat concat size end catch inspect do def each concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat size loop do break concat concat size end loop do break concat concat size end loop do break clear end loop do break concat concat size end loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat begin dup ensure clear concat concat concat size loop do break concat concat size end loop do break concat concat size end loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear concat concat concat concat size concat concat concat concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear concat concat concat size loop do break concat concat size end concat concat concat size loop do break concat concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat size loop do break concat concat size end loop do break concat concat size end loop do break concat concat size end loop do break concat concat size end loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat size loop do break concat size end loop do break concat concat size end concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat size concat begin size ensure clear end end loop do break concat concat size end concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end concat concat concat concat size concat begin dup ensure clear concat concat concat size loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear concat concat concat concat size concat concat concat concat size concat concat concat concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear concat concat concat concat size loop do break concat concat size end loop do break concat concat size end loop do break concat size end loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat concat concat concat size loop do break concat concat size end loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat concat concat size concat concat concat size concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat concat concat size concat concat concat size loop do break concat size end concat begin size ensure clear end end concat begin dup ensure clear loop do break concat concat size end loop do break concat concat size end concat concat concat concat concat size concat begin size ensure clear end end loop do break eval self end loop do exit end end end for each in inspect do 30 copyright mmxii yusuke end o h
    • 関連研究: 他の文字制限の例 _=[* ..?~]*;$><<_[(___=_=~/@/• 記号だけ (kurimura [2008]) ).+_=~/¥(/]+_[(__=_=~/_/).+_=~/&/ ]+_[__+@@_=_=~/¥-/]+_[__+@@_]+_[( @_=_=~/~/)-@@_=_=~/¥//]+", "+_[ @_.-_=~//]+_[@_-@@_]+_[@_.-_=~ /,/]+_[__.+_=~/¥-/]+_[__.+_=~/%/ ]+?!+$/• 数字(+ require)だけ require "1234567890" 316805813369061470447252554255354 816767578747985092956934801232229 450578663292118901228453190669621 8369564670777459615871118090530 require "_"• アンダースコア(+ require) ____ _ _____ ____ __ ____ ____ __ ___ ____ __ __ _ ______ _____ だけ ___ _ _ ___ _____ ______ ____ _ _ ____ _ _ ____ _ ____ __ __ ___ _ ______ ___ ____ __ ______ ____ _ ____ ____ __ _ ____ _ _ ___ _____ _____ _ ______ ____ _ ______ _____ 31
    • 関連研究: 他言語での文字制限の例• Perl: 記号だけ (Takesako [2005]) Quiz: これは何をするプログラムでしょう? まとめ  Let’s 予約語プログラミング♪ #!/usr/bin/perl  Perl 以外の言語でも実装できますか? sin cos and s qq qx xor s x x print uc chr lc  awk ? ord qq sleep times x xor int log cos xor eval  Haskell ? Lisp ? and eval and print uc chr ord scalar reverse   ML ? qq exit binmode xor qq write qw xor print uc  Perl → OK ! chr ord scalar reverse qw tell my print  PHP ?  Python ? 挑戦者求む!  Ruby ? 正解 → 標準出力に “LLDN” という文字列を出力するプログラム2005/08/27 Lightweight Language Day and Night 4 2005/08/27 Lightweight Language Day and Night 18• Javascript – 記号だけ (Hasegawa [?]) – 顔文字だけ (Hasegawa [?]) 32
    • 目次• 背景: 近年のプログラミングの問題• 提案: 超絶技巧プログラミング – 実践1: self-descriptive な Ruby プログラム – 実践2: 文字を制限された Ruby プログラム• まとめ 33
    • まとめ• 超絶技巧プログラミングを紹介した – 実用性を無視して「美しい」プログラミング• みなさんもいかがでしょうか – IOCCC開催中  – 9/15 まで 34