Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Transcendental Programming in Ruby

Transcendental Programming in Ruby

Yusuke Endoh

November 10, 2018
Tweet

More Decks by Yusuke Endoh

Other Decks in Programming

Transcript

  1. Yusuke Endoh (@mametter) • A MRI committer (2008..) – Keyword

    arguments – Test suite improvement – coverage.so (backend of SimpleCov) – OptCarrot: A benchmark for Ruby3x3 • Working at Cookpad Inc. – As a full-time Ruby committer (with Koichi Sasada)
  2. • A recipe sharing platform service – Monthly Average Users:

    90 million – https://cookpad.com/uk PR: Cookpad Inc. We're hiring! HQ is in Bristol Aim to be No.1 in 100 countries (Now in 22 Languages and 68 Countries)
  3. Transcendental programming • Enjoy programming regardless of practicality – Forget

    usefulness, secular benefits, and the weary world, and just do programming – Abuse a useful programming language to write a completely useless program
  4. A Ruby program require "doublehelix" AT A--T T---A G----C G----C

    G----C T---A G--C AT GC T--A G---C T----A A----T T----A G---C C--G AT CG A--T A---T C----G A----T G----C G---C G--C CG GC A--T T---A C----G G----C A----T T---A C--G GC TA T--A C---G G----C A----T T----A C---G require "doublehelix" AT A--T T---A G----C G----C G----C T---A G--C AT GC T--A
  5. Demo • "Hello, world!" program in doublehelix – You can

    encode not only Hello world, but also any Ruby programs $ ruby doublehello.rb Hello-hello! doublehelix
  6. Internal • Gödel numbering – Converts a program text to

    a number • Text to number: str.unpack("H*")[0].hex • Number to text: [num.to_s(16)].pack("H*") • Double-helix encoding and decoding doublehelix
  7. Internal: Double-helix encoding • Convert the number in binary notation

    • And each two digits to AT/CG/GC/TA doublehelix 0000111010... puts"Hello-hello!" Gödel numbering 00 00 11 10 10 AT AT TA GC GC AT A--T T---A G----C G----C ...
  8. Internal: Double-helix decoding • const_missing – Restore the number, decode

    it to the code, and eval • One more trick is needed... doublehelix Object.instance_eval{ def const_missing(sym) p sum end } remove_const(:GC) AT #=> :AT A--T #=> :A, :T T---A #=> :T, :A G----C #=> :G, :C G----C #=> :G, :C
  9. How to install – Acknowledge: This program was inspired by

    Perl's Acme::DoubleHelix doublehelix $ gem install doublehelix
  10. Scanned result #!ruby # Q(uine)R(uby)code (C) Y.Endoh 2009 eval s=%q(X=(0..7).map{|i|1<<i};W=116;m=(1..w=117).map{[]};B=999.times{|i|X<<(

    X[-4]^X[-5]^X[-6]^X[-8]);n=0x7f415d5d5d417f;i<64&&m[j=i/8][k=i%8]=m[W-j][k]=m[ j][W-k]=n[i]};P=6.step 110,26;P.map{|j|P.map{|k|m[j][k]||25.times{|i|m[j-2+i/5 ][k-2+i%5]=-469441[i]}}};g=[1];m[109.times{|i|m[i][6]=m[6][i]||=1-i;i<15&&m[i. +i<6?0:i<8?1:102][8]=m[8][(i>8?14:i>7?15:W)-i]=26998[i];i<18&&m[i/3][x=i%3+106 ]=m[x][i/3]=102881[i];i<26&&g=(g+[0]).zip([0]+g.map{|x|X[i+X.index(x)]}).map{| x,y|x^y}}][8]=1;_,*G=g;n=c=12704;b=("404e4#{"%02x"*1252}0#{"ec11"*B}"%%(#!ruby # Q(uine)R(uby)code (C) Y.Endoh 2009¥neval s=%q(#{s})).unpack("C*")).scan /../ D=[];E=([106]*8+[107]*4).map{|d|D<<y=b.shift(d).map(&:hex);z=y+G.map{0};y.map{ r=X.index z.shift;r&&z=z.zip(G).map{|y,x|x ?y^X[r+X.index(x)]:y}};z};require"¥ zlib";(D*B+E*B).map{|l|x=l.shift;x&&n=x+n*256};x=13688;d=[1,W];x.times{m[i=x/w ][j=x%w]||=n[c-=1]^i+j+i*j%3+1;x-=y=d.shift;d<<y;0<=x&&x<w*w||x-=3+d[1]=-2-y ; x==6&&x=5};z,e="¥0","¥xff";t=(z+e*125)*16;s="IDAT"+Zlib::Deflate.deflate(t+m . map{|l|[z,e*4,l.map{|x|(e+z)[x&1,1]},e*4]*4}*""+t);print ["¥x89PNG¥r¥n¥x1a¥n", 13,"IHDR",500,500,2,0,2752354551,s.size-4,s,Zlib.crc32(s),0,"IEND¥xAEB`¥x82"]. pack"A*NA*NNCN3A*NNA*") QR code?
  11. Q(uine)R(uby) code #!ruby # Q(uine)R(uby)code (C) Y.Endoh 2009 eval s=%q(X=(0..7).map{|i|1<<i};W=116;m=(1..w=117).map{[]};B=999.times{|i|X<<(

    X[-4]^X[-5]^X[-6]^X[-8]);n=0x7f415d5d5d417f;i<64&&m[j=i/8][k=i%8]=m[W-j][k]=m[ j][W-k]=n[i]};P=6.step 110,26;P.map{|j|P.map{|k|m[j][k]||25.times{|i|m[j-2+i/5 ][k-2+i%5]=-469441[i]}}};g=[1];m[109.times{|i|m[i][6]=m[6][i]||=1-i;i<15&&m[i. +i<6?0:i<8?1:102][8]=m[8][(i>8?14:i>7?15:W)-i]=26998[i];i<18&&m[i/3][x=i%3+106 ]=m[x][i/3]=102881[i];i<26&&g=(g+[0]).zip([0]+g.map{|x|X[i+X.index(x)]}).map{| x,y|x^y}}][8]=1;_,*G=g;n=c=12704;b=("404e4#{"%02x"*1252}0#{"ec11"*B}"%%(#!ruby # Q(uine)R(uby)code (C) Y.Endoh 2009¥neval s=%q(#{s})).unpack("C*")).scan /../ D=[];E=([106]*8+[107]*4).map{|d|D<<y=b.shift(d).map(&:hex);z=y+G.map{0};y.map{ r=X.index z.shift;r&&z=z.zip(G).map{|y,x|x ?y^X[r+X.index(x)]:y}};z};require"¥ zlib";(D*B+E*B).map{|l|x=l.shift;x&&n=x+n*256};x=13688;d=[1,W];x.times{m[i=x/w ][j=x%w]||=n[c-=1]^i+j+i*j%3+1;x-=y=d.shift;d<<y;0<=x&&x<w*w||x-=3+d[1]=-2-y ; x==6&&x=5};z,e="¥0","¥xff";t=(z+e*125)*16;s="IDAT"+Zlib::Deflate.deflate(t+m . map{|l|[z,e*4,l.map{|x|(e+z)[x&1,1]},e*4]*4}*""+t);print ["¥x89PNG¥r¥n¥x1a¥n", 13,"IHDR",500,500,2,0,2752354551,s.size-4,s,Zlib.crc32(s),0,"IEND¥xAEB`¥x82"]. pack"A*NA*NNCN3A*NNA*") Scan Execute Q(uine)R(uby) code
  12. Internal • Quine (& QR-encoder, PNG-generator) #!ruby # Q(uine)R(uby)code (C)

    Y.Endoh 2009 eval s=%q(X=(0..7).map{|i|1<<i};W=116;m=(1..w=117).map{[]};B=999.times{|i|X<<( X[-4]^X[-5]^X[-6]^X[-8]);n=0x7f415d5d5d417f;i<64&&m[j=i/8][k=i%8]=m[W-j][k]=m[ j][W-k]=n[i]};P=6.step 110,26;P.map{|j|P.map{|k|m[j][k]||25.times{|i|m[j-2+i/5 ][k-2+i%5]=-469441[i]}}};g=[1];m[109.times{|i|m[i][6]=m[6][i]||=1-i;i<15&&m[i. +i<6?0:i<8?1:102][8]=m[8][(i>8?14:i>7?15:W)-i]=26998[i];i<18&&m[i/3][x=i%3+106 ]=m[x][i/3]=102881[i];i<26&&g=(g+[0]).zip([0]+g.map{|x|X[i+X.index(x)]}).map{| x,y|x^y}}][8]=1;_,*G=g;n=c=12704;b=("404e4#{"%02x"*1252}0#{"ec11"*B}"%%(#!ruby # Q(uine)R(uby)code (C) Y.Endoh 2009¥neval s=%q(#{s})).unpack("C*")).scan /../ D=[];E=([106]*8+[107]*4).map{|d|D<<y=b.shift(d).map(&:hex);z=y+G.map{0};y.map{ r=X.index z.shift;r&&z=z.zip(G).map{|y,x|x ?y^X[r+X.index(x)]:y}};z};require"¥ zlib";(D*B+E*B).map{|l|x=l.shift;x&&n=x+n*256};x=13688;d=[1,W];x.times{m[i=x/w ][j=x%w]||=n[c-=1]^i+j+i*j%3+1;x-=y=d.shift;d<<y;0<=x&&x<w*w||x-=3+d[1]=-2-y ; x==6&&x=5};z,e="¥0","¥xff";t=(z+e*125)*16;s="IDAT"+Zlib::Deflate.deflate(t+m . map{|l|[z,e*4,l.map{|x|(e+z)[x&1,1]},e*4]*4}*""+t);print ["¥x89PNG¥r¥n¥x1a¥n", 13,"IHDR",500,500,2,0,2752354551,s.size-4,s,Zlib.crc32(s),0,"IEND¥xAEB`¥x82"]. pack"A*NA*NNCN3A*NNA*") • Quine • QR-encoder – Solomon-Reed encoding – Pattern generation • PNG-generator Q(uine)R(uby) code
  13. Quine • A program that outputs itself – Step 1.

    Reconstruct self as a string – Step 2. Print it • Additional step makes Quine "funny" eval s="print('eval s='+s.inspect)" Q(uine)R(uby) code
  14. What is this? eval s=%w(0;y=""< <32;z="eval((;s=%w(#{s} )*''));; %" <<43<<s; d="";"

    0v vvnvn2 mj4kil 0v lvvul2 6l94ol 0v lv7vv" .scan (/ .{7}/ ){|n| 2. times {d.< <T ime. now. to_s.unpack(" C*") [11, 8].map{|i|("% 03b" .%7&n .to_i (32)> >3*i- =48).g sub(/. /){s>$ &?y*3: z.slic e!(0,3 )}}*y<<1 0}};puts (d.strip.chop<<43))*''# #(c) Y.Endoh 2009
  15. Demo • It tells time as a code that tells

    time $ ruby qlock.rb eval(( ;s=%w(0;y =""<<32;z ="eval((; s=%w(#{s} )*''));;% "<<43< <s;d="";" 0vvvnvn2m j4kil0vlv vul26l94o l0vlv7vv" .sc an( /.{ 7}/ ){| n|2 .ti mes {d. <<T ime .no w.t o_s .un pac k(" C*" )[1 1,8 ].m ap{ |i| ("% 03b ".%7&n.to _i( 32) >>3 *i- =48 ).g sub (/. /){ s>$&?y*3: z.s lic e!( 0,3 )}} *y< <10 }}; put s(d .st rip .ch op< <43 ))* '') );; %+0 ;y= ""< <32 ;z= "ev al( (;s =%w (#{ s}) *'' )); ;%" <<43<<s;d ="";"0vvv nvn2mj4ki l0vlvvul2 6l94ol0vl v7vv".sca n(/.{7}/) {|n|2.tim es{d.<<Ti me.now.to _s.unpack ("C*")[1+ Qlock
  16. Internal (digest) • Quine + Font + Executable ASCII-art eval

    s=%w(0;y=""< <32;z="eval((;s=%w(#{s} )*''));; %" <<43<<s; d="";" 0v vvnvn2 mj4kil 0v lvvul2 6l94ol 0v lv7vv" .scan (/ .{7}/ ){|n| 2. times {d.< <T ime. now. to_s.unpack(" C*") [11, 8].map{|i|("% 03b" .%7&n .to_i (32)> >3*i- =48).g sub(/. /){s>$ &?y*3: z.slic e!(0,3 )}}*y<<1 0}};puts (d.strip.chop<<43))*''# #(c) Y.Endoh 2009 • Quine • Clock generator – Font data – ASCII-art generator • See my RubyConf talk for the details – https://www.youtube.com/ watch?v=6K7EmeptEHo Qlock
  17. What is this? '';eval(r=%q(->z{r="'';eval(r=¥ %q(#{r}))[%q`#{z}`]";i=-040;30. times{|n|(15+n%2*15-n/2).times{ r<<r[i+=(1.-n&2)*(32-n%2*31)]}} i=r[524,0]=?¥0;eval(r[479..-1]) c['"']}))[%q`GFEDCBA"+"[e¥"'"'t kE*;;¥";"

    TRICK2018 ";tb,;{{r 2E0$ob[us@*0)[90,336])_#i¥n}s#i 0H}>["t]];};o[1,?¥n*8];ex"-}eac 1Hl<1[-1]*2*t=n%2];o[14-n,0)mvk 8M$<4,?¥n];15.times{|n|;o[35ie2 !Pss.slice!(0,1)+x;sleep(0.0t;0 'W=%q"<<95<<$s<<95;o=->n,x{n.'1 ;@[2]}|¥e../,%@s="'%trick2018!8 eval$s=%q_eval($s.gsub!(/#{%@`]
  18. Internal • Quine + Animation – Use escape sequence to

    move the cursor – The output includes many escape sequences, so not a valid Ruby code...? print "¥e[1A" #=> move up print "¥e[1B" #=> move down print "¥e[1C" #=> move right print "¥e[1D" #=> move left Spiral Quine
  19. Music-box Quine 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 # | # | # # # # # | | | # | | # # # # # # | | | # | | # # # # # #
  20. Internal • Quine + Music player – Synthesize sound waves

    – And send them to the sound driver (/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 # | # | # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # | | | # | #| # # # | # | | | # | | # # # # # # | | # | | | # # # # # # | | | # | | # # # # # | | # | | # # | # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | | # # # # # # | | | # | # # # # # | | | # | # | # # # # # | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | : Sound Synth. Music Data
  21. Lipogram Quine format= %%->{#({#){#.{#0{#1{#2{#3{#4{#5{#6{#7{#8{#9{#h{#k{#l{#p{#v{#w{#<{#*{#a{#b{#c{#d{#e{#f{; t=->s,x,y{->&u{u[s,x,y]}[&:tr]};z="!-{";->&u{u[y="().0123456789hklpvw<*abcdef¥¥",t["m~i",",-~", "$-{"]+t["$",z,"i-{"],t[t["YQUO@g=`@W='@ABCDEFGHIJKLMNOPQRSTUVWXYZ';g=^YQUO@g=`@^+g+^AA^;Y=?=;n =Y+OoWUO_Q UriUVOYsTY+Y;x=- >s{sBVyt Ys};q,=n[u

    =^ZormUt^]?@u =ZormUtA?[ DC,TFEBBDEI]-x[u +?`]:x[W +?`]-x[y]: n=~/=Z?o?r?m? U?t?=/?x[u ]-x[$&]:Y;z='ZormUt= C``->{H{Dt=- >s,x,y {Js,x, y]}[&: tr]};z=^!-{ ^;Jy=^I^,t [^m~iK,-~K$-{^]+t[^$ ^,z,^i-{^],t [t[^EK C^+$/, ^^],^G ^,t[^qntuz| yKm-|^,z]+ t[^;jmnrxy>,K&-{K$-{ ^]+t[^o;tK/- {^,z]] ]}[&Jt [^xjsi K&-{^,z]]}[ &:to_sym]] }[]`;DYQUO^@YQUO@@`R ``SS`R`F`T`` `ABPUW N@``MT `AAA^' BgsuV@/[C-L ]/A{[FEBWM r,$/,gBtr@'`^'+W,j=L IBWMrSSLGSSI GSSGHSSL CA,TgB unPUWN@^MT^ A,j,?#+WBW MUrsT^{#^,W+LEBWMrTE ,^->&u{u[^,' ^,^'][YQ UO$&]} ;GGBtimYs{| y|Print@@@ CBBLGABmUP{|x|^qZXzm uDHjtVOCuVnO ooCYHWIJyrnonDmE GtijRU oNFxGWXxuOm CmIEYRXsgZ EgqOKQMGHJOKQnYuuVYy IrCEmrPqVgno irYDnnxLDjZWCGyN nZmnIy zKXignRYPnz DuCYgMHyyM JjqWYD ODruUPCm DtqFqFDCrrJVxXJzOg MWQGNnUuio^Bt o_i@FIA[x/ E-D+@y +DA/ETGI ]>C?@FEBWMrA:@z[C] ==$/||!z[C]?? ;:zBsOiWY!@C,DAA}T^^+$/ABtr@@!$T[C]&&q||CABWMr,^^AA;z[C]==$/&&z[C]=^^};Yxit;;;;;;;AA"," "+$/,"" ],"`^@-Z",t["qntuz|y","m-|",z]+t[";jmnrxy>,","&-{","$-{"]+t["o;t","/-{",z]]]}[&->&u{u[t["xjsi", "&-{",z]]}[&:to_sym]]}[]%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; eval"(eval((%w%%<<%w%566716c68276d3528236d3728292e20313233343536373839386b6c6076777c3a216263646 566672b376d322566716c68276d3528222b276b222929222b356d3f3d3b3e6d356b2c6f63616c6f5671627961626c65 637a256b256b387d3d2e337b737e22697475637d7b317c2d3e6b557d32266f627d6164722d5f38257d366f627d61647 92f3b51303c2a23323e2e2132363d5d287b557b2f352d5a387b536b2f352d5d287b597d5a3e6d3e7f2d366f3f6f327f 3d6f316f347f3d3f2f387b557d5d287b54262d5a356b3a7d37266f627d61647d3035252d2e3b753b71347d3d2e337c2 87c297b77337c287c297d5d7b562a34727d5d7b3a7d32212d2b722b37397d3226322c247b522d6e79683c2d2e78342d 2b722d5b247b5224222c2a7c22296d2b722d5c247b547b52223830322b242f2c22222d5c2224322c247b52217e64757 a7c79783d6d2c7 22c2a7 d5b247b522b3 a6d6e62787 97e3c2 8362d2b7834 2d2b722d5b247b 522f6b 34783f2d2b72 2c2a7d5d5d 5d7b56 27347b52287 a637968362d2 b722c2a7d5d5d7 b562a3 47f6f537 97 d6d5d5d7 b5 d552b313566 716c62282566 716c6828252775 252c3c 35277523 35 2a252525 29 2e2071636b6 82525286a2 529292922272e276 375726 82f2b5 03d293 d5f292 b7b53323e23 68627c242f 2c276e2472782725 22272b 236c2a 6d3936 3e2368 627c3c39343 c3c36343c3 c343 53c3c3 930392 c2a276 e257e6 071636 b6 82 2286a22292c 2a6c2f332b 236e 236861 62737a 222b73 222c23 6b2932 3e 23 68627a223c2 22d2e36257 b757b5 22c272 22c22272d5 b55667 16 c6 4262d5d7b34 343e24796d 65637b 7c797c 7072796e64 782828 20 3e 2e2934392e2 d61607b7c787 c722 176646 a7d6 571353a6 4726c6 035726 e6c6f6 f6035653366 3739727e6f6e 613d 623434 796a 67716f6b 633874 336468 757c6d 603d6632356 77463776662376 17c683 678643 5373c6 8367e6 565757 265697 63270323d62 707172676e6f69 627561 3e6e68 79313a 666360 34397b 6e666d 6e66397a783 469676e6775607e6a71357035676865397978673a617365613c6132757160703d613471733173313032727732687467 3a7c67686366743b6e6165796f622e247f6f59682336392b587f223d213b28297b21392f223a24363d5e303f3823323 e236862792a382a7b503d5d3d342f2c7c712a7b503d5f3f3b3a3a7e237c6963656128203c2139292d7a22222b242f29 2e2472782821242a2b503d5626217c7c70392e2368627c222229292b3a7b503d5d3d342f26262a7b503d5d32222d7b3 56879647b3b3b3b3b3b3b39292%*%%%).pack(%%h*%)))";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  22. Demo • Works as an ordinary Quine $ ruby lquine.rb

    > lquine2.rb $ diff –s lquine.rb lquine2.rb lquine.rb and lquine2.rb are identical Lipogram Quine
  23. "a" is removed from the world! format= %%->{#({#){#.{#0{#1{#2{#3{#4{#5{#6{#7{#8{#9{#h{#k{#l{#p{#v{#w{#<{#*{#a{#b{#c{#d{#e{#f{; t=->s,x,y{->&u{u[s,x,y]}[&:tr]};z="!-{";->&u{u[y="().0123456789hklpvw<*abcdef¥¥",t["m~i",",-~", "$-{"]+t["$",z,"i-{"],t[t["YQUO@g=`@W='@ABCDEFGHIJKLMNOPQRSTUVWXYZ';g=^YQUO@g=`@^+g+^AA^;Y=?=;n

    =Y+OoWUO_Q UriUVOYsTY+Y;x=- >s{sBVyt Ys};q,=n[u =^ZormUt^]?@u =ZormUtA?[ DC,TFEBBDEI]-x[u +?`]:x[W +?`]-x[y]: n=~/=Z?o?r?m? U?t?=/?x[u ]-x[$&]:Y;z='ZormUt= C``->{H{Dt=- >s,x,y {Js,x, y]}[&: tr]};z=^!-{ ^;Jy=^I^,t [^m~iK,-~K$-{^]+t[^$ ^,z,^i-{^],t [t[^EK C^+$/, ^^],^G ^,t[^qntuz| yKm-|^,z]+ t[^;jmnrxy>,K&-{K$-{ ^]+t[^o;tK/- {^,z]] ]}[&Jt [^xjsi K&-{^,z]]}[ &:to_sym]] }[]`;DYQUO^@YQUO@@`R ``SS`R`F`T`` `ABPUW N@``MT `AAA^' BgsuV@/[C-L ]/A{[FEBWM r,$/,gBtr@'`^'+W,j=L IBWMrSSLGSSI GSSGHSSL CA,TgB unPUWN@^MT^ A,j,?#+WBW MUrsT^{#^,W+LEBWMrTE ,^->&u{u[^,' ^,^'][YQ UO$&]} ;GGBtimYs{| y|Print@@@ CBBLGABmUP{|x|^qZXzm uDHjtVOCuVnO ooCYHWIJyrnonDmE GtijRU oNFxGWXxuOm CmIEYRXsgZ EgqOKQMGHJOKQnYuuVYy IrCEmrPqVgno irYDnnxLDjZWCGyN nZmnIy zKXignRYPnz DuCYgMHyyM JjqWYD ODruUPCm DtqFqFDCrrJVxXJzOg MWQGNnUuio^Bt o_i@FIA[x/ E-D+@y +DA/ETGI ]>C?@FEBWMrA:@z[C] ==$/||!z[C]?? ;:zBsOiWY!@C,DAA}T^^+$/ABtr@@!$T[C]&&q||CABWMr,^^AA;z[C]==$/&&z[C]=^^};Yxit;;;;;;;AA"," "+$/,"" ],"`^@-Z",t["qntuz|y","m-|",z]+t[";jmnrxy>,","&-{","$-{"]+t["o;t","/-{",z]]]}[&->&u{u[t["xjsi", "&-{",z]]}[&:to_sym]]}[]%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; eval"(eval((%w%%<<%w%566716c68276d3528236d3728292e20313233343536373839386b6c6076777c3a216263646 566672b376d322566716c68276d3528222b276b222929222b356d3f3d3b3e6d356b2c6f63616c6f5671627961626c65 637a256b256b387d3d2e337b737e22697475637d7b317c2d3e6b557d32266f627d6164722d5f38257d366f627d61647 92f3b51303c2a23323e2e2132363d5d287b557b2f352d5a387b536b2f352d5d287b597d5a3e6d3e7f2d366f3f6f327f 3d6f316f347f3d3f2f387b557d5d287b54262d5a356b3a7d37266f627d61647d3035252d2e3b753b71347d3d2e337c2 87c297b77337c287c297d5d7b562a34727d5d7b3a7d32212d2b722b37397d3226322c247b522d6e79683c2d2e78342d 2b722d5b247b5224222c2a7c22296d2b722d5c247b547b52223830322b242f2c22222d5c2224322c247b52217e64757 a7c79783d6d2c7 22c2a7 d5b247b522b3 a6d6e62787 97e3c2 8362d2b7834 2d2b722d5b247b 522f6b 34783f2d2b72 2c2a7d5d5d 5d7b56 27347b52287 a637968362d2 b722c2a7d5d5d7 b562a3 47f6f537 97 d6d5d5d7 b5 d552b313566 716c62282566 716c6828252775 252c3c 35277523 35 2a252525 29 2e2071636b6 82525286a2 529292922272e276 375726 82f2b5 03d293 d5f292 b7b53323e23 68627c242f 2c276e2472782725 22272b 236c2a 6d3936 3e2368 627c3c39343 c3c36343c3 c343 53c3c3 930392 c2a276 e257e6 071636 b6 82 2286a22292c 2a6c2f332b 236e 236861 62737a 222b73 222c23 6b2932 3e 23 68627a223c2 22d2e36257 b757b5 22c272 22c22272d5 b55667 16 c6 4262d5d7b34 343e24796d 65637b 7c797c 7072796e64 782828 20 3e 2e2934392e2 d61607b7c787 c722 176646 a7d6 571353a6 4726c6 035726 e6c6f6 f6035653366 3739727e6f6e 613d 623434 796a 67716f6b 633874 336468 757c6d 603d6632356 77463776662376 17c683 678643 5373c6 8367e6 565757 265697 63270323d62 707172676e6f69 627561 3e6e68 79313a 666360 34397b 6e666d 6e66397a783 469676e6775607e6a71357035676865397978673a617365613c6132757160703d613471733173313032727732687467 3a7c67686366743b6e6165796f622e247f6f59682336392b587f223d213b28297b21392f223a24363d5e303f3823323 e236862792a382a7b503d5d3d342f2c7c712a7b503d5f3f3b3a3a7e237c6963656128203c2139292d7a22222b242f29 2e2472782821242a2b503d5626217c7c70392e2368627c222229292b3a7b503d5d3d342f26262a7b503d5d32222d7b3 56879647b3b3b3b3b3b3b39292%*%%%).pack(%%h*%)))";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $ sed s/a//g lquine.rb Lipogram Quine
  24. "" is removed from the world! formt= %%->{#({#){#.{#0{#1{#2{#3{#4{#5{#6{#7{#8{#9{#h{#k{#l{#p{#v{#w{#<{#*{#{#b{#c{#d{#e{#f{; t=->s,x,y{->&u{u[s,x,y]}[&:tr]};z="!-{";->&u{u[y="().0123456789hklpvw<*bcdef¥¥",t["m~i",",-~", "$-{"]+t["$",z,"i-{"],t[t["YQUO@g=`@W='@ABCDEFGHIJKLMNOPQRSTUVWXYZ';g=^YQUO@g=`@^+g+^AA^;Y=?=;n

    =Y+OoWUO_Q UriUVOYsTY+Y;x=- >s{sBVyt Ys};q,=n[u =^ZormUt^]?@u =ZormUtA?[ DC,TFEBBDEI]-x[u +?`]:x[W +?`]-x[y]: n=~/=Z?o?r?m? U?t?=/?x[u ]-x[$&]:Y;z='ZormUt= C``->{H{Dt=- >s,x,y {Js,x, y]}[&: tr]};z=^!-{ ^;Jy=^I^,t [^m~iK,-~K$-{^]+t[^$ ^,z,^i-{^],t [t[^EK C^+$/, ^^],^G ^,t[^qntuz| yKm-|^,z]+ t[^;jmnrxy>,K&-{K$-{ ^]+t[^o;tK/- {^,z]] ]}[&Jt [^xjsi K&-{^,z]]}[ &:to_sym]] }[]`;DYQUO^@YQUO@@`R ``SS`R`F`T`` `ABPUW N@``MT `AAA^' BgsuV@/[C-L ]/A{[FEBWM r,$/,gBtr@'`^'+W,j=L IBWMrSSLGSSI GSSGHSSL CA,TgB unPUWN@^MT^ A,j,?#+WBW MUrsT^{#^,W+LEBWMrTE ,^->&u{u[^,' ^,^'][YQ UO$&]} ;GGBtimYs{| y|Print@@@ CBBLGABmUP{|x|^qZXzm uDHjtVOCuVnO ooCYHWIJyrnonDmE GtijRU oNFxGWXxuOm CmIEYRXsgZ EgqOKQMGHJOKQnYuuVYy IrCEmrPqVgno irYDnnxLDjZWCGyN nZmnIy zKXignRYPnz DuCYgMHyyM JjqWYD ODruUPCm DtqFqFDCrrJVxXJzOg MWQGNnUuio^Bt o_i@FIA[x/ E-D+@y +DA/ETGI ]>C?@FEBWMrA:@z[C] ==$/||!z[C]?? ;:zBsOiWY!@C,DAA}T^^+$/ABtr@@!$T[C]&&q||CABWMr,^^AA;z[C]==$/&&z[C]=^^};Yxit;;;;;;;AA"," "+$/,"" ],"`^@-Z",t["qntuz|y","m-|",z]+t[";jmnrxy>,","&-{","$-{"]+t["o;t","/-{",z]]]}[&->&u{u[t["xjsi", "&-{",z]]}[&:to_sym]]}[]%;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; evl"(evl((%w%%<<%w%566716c68276d3528236d3728292e20313233343536373839386b6c6076777c3216263646 566672b376d322566716c68276d3528222b276b222929222b356d3f3d3b3e6d356b2c6f63616c6f5671627961626c65 637256b256b387d3d2e337b737e22697475637d7b317c2d3e6b557d32266f627d6164722d5f38257d366f627d61647 92f3b51303c223323e2e2132363d5d287b557b2f352d5387b536b2f352d5d287b597d53e6d3e7f2d366f3f6f327f 3d6f316f347f3d3f2f387b557d5d287b54262d5356b37d37266f627d61647d3035252d2e3b753b71347d3d2e337c2 87c297b77337c287c297d5d7b56234727d5d7b37d32212d2b722b37397d3226322c247b522d6e79683c2d2e78342d 2b722d5b247b5224222c27c22296d2b722d5c247b547b52223830322b242f2c22222d5c2224322c247b52217e64757 7c79783d6d2c7 22c27 d5b247b522b3 6d6e62787 97e3c2 8362d2b7834 2d2b722d5b247b 522f6b 34783f2d2b72 2c27d5d5d 5d7b56 27347b52287 637968362d2 b722c27d5d5d7 b5623 47f6f537 97 d6d5d5d7 b5 d552b313566 716c62282566 716c6828252775 252c3c 35277523 35 2252525 29 2e2071636b6 825252862 529292922272e276 375726 82f2b5 03d293 d5f292 b7b53323e23 68627c242f 2c276e2472782725 22272b 236c2 6d3936 3e2368 627c3c39343 c3c36343c3 c343 53c3c3 930392 c2276 e257e6 071636 b6 82 228622292c 26c2f332b 236e 236861 62737 222b73 222c23 6b2932 3e 23 68627223c2 22d2e36257 b757b5 22c272 22c22272d5 b55667 16 c6 4262d5d7b34 343e24796d 65637b 7c797c 7072796e64 782828 20 3e 2e2934392e2 d61607b7c787 c722 176646 7d6 5713536 4726c6 035726 e6c6f6 f6035653366 3739727e6f6e 613d 623434 796 67716f6b 633874 336468 757c6d 603d6632356 77463776662376 17c683 678643 5373c6 8367e6 565757 265697 63270323d62 707172676e6f69 627561 3e6e68 79313 666360 34397b 6e666d 6e66397783 469676e6775607e671357035676865397978673617365613c6132757160703d613471733173313032727732687467 37c67686366743b6e6165796f622e247f6f59682336392b587f223d213b28297b21392f22324363d5e303f3823323 e2368627923827b503d5d3d342f2c7c7127b503d5f3f3b337e237c6963656128203c2139292d722222b242f29 2e24727828212422b503d5626217c7c70392e2368627c222229292b37b503d5d3d342f262627b503d5d32222d7b3 56879647b3b3b3b3b3b3b39292%*%%%).pck(%%h*%)))";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; $ sed s/a//g lquine.rb Lipogram Quine
  25. Demo • You can delete any one letter • It

    automatically restore itself! $ sed s/a//g lquine.rb > broken.rb $ ruby broken.rb > broken2.rb $ diff –s broken.rb broken2.rb broken.rb and broken2.rb are identical Lipogram Quine
  26. Internal • Main trick: – This code executes code2 •

    The string literal is just ignored • If "a" is removed: – This code executes code1 and terminates Lipogram Quine "#a{ code1;exit }"; code2 "#{ code1;exit }"; code2 String interpolation!
  27. Internal • Basic structure: Lipogram Quine "#a{#b{#c{… A code without

    "a","b","c",… exit }" A code with only "a","b","c",…
  28. More? • My book: "The World of Obfuscated, Esoteric, Artistic

    Programming" – Contains about 40 codes like this talk – Written in Japanese • TRICK: Transcendental Ruby Imbroglio Contest for rubyKaigi – You can enjoy the previous winners – https://github.com/tric/
  29. Conclusion • Ruby is so powerful and weird – Weirder

    than you know – Need to keep it weirder? ☺ • Ruby Programming is fun – Even without practicality – If you like practicality, join 
  30. "Keep Ruby Weird" %q!.!;eval$s=%q{eval(%w{$s=("%q!.!;eval$s=%q{#$s}"+'.gsub(/#{27.chr<<92<<91}[0-9]+m/,"")').lines;C=->x,y{Complex(x,y)};P=->r,a{Complex.polar(r,a*Math::PI)};S=->((a,b),(c ,d)){[a-c,b-d]};D=->((a,b),(c,d)){(a*c.conj).real+b*d};R=->((a,b),(c,d)){e,f=a.rect;g,h=c.rect;[C[f*d-b*h,b*g-e*d],e*h-f*g]};a=[];b=[];6.times{|i|a<<[P[1,i/3.0],1];b<<[P [2,(i+0.5)/3.0],0]};F=[a];6.times{|j|F<<[a[i=j-1],b[i],a[j]]<<[a[j],b[i],b[j]]<<[b[i],[0,-2],b[j]]};J=->k,v{k=[k/500.0,0].min+2.5;(v/(k+0.5)+C[k,k/2])*48};r=0;T=->p{x,y= p.rect;z =O[y/2];x>=0&&y>=0&&z&&z[x]&&z[x]|=(y%2>1?2:1)|r};L=->p,q{s=(p+q)/2;(p-q).abs<1?(T[s];q):L[L[p,s],q]};N=->((a,b)){s=(a.abs2+b*b)**0.5;[a/s,b/s]};E=->p,r,a{10 0.times {|

    i|m=-P[r,1.5+i*a*0.02];c,d=(p+m).rect;(c.abs-d>2||d<-1)&&(T[J[0,p+m]];T[J[0,C[-c,d ]]])}};A=27.chr;$><<"%q#{33. chr+A}[H#{A}[2J";g="NZDD CLYJXMX ;Y K(OQ'PP YZA5YTZ7M(VOBBSYVXQQ[SUZV(U:G[NVZ[ZS&V[(YUU(ZTT[[X'X&Y%Y'ZZWW['Z&$$[%('' '(&[$(%($( CRGZHZI)DIOZ;IVPZ(SP)[X* DRZCGJJT<< +XI,%%:S=[E==RE&LEXX-'. RMY:(>>U(HU /U[/[R KOO0Y$1F?LZ%&M@(2NGU341RU?+6S2(NVYVAFVR(8FFRYRN4W'NHI@>(EUM6H@ZISSMS-XL .LLVL?RR8O[O K9B,$%Y[3Y0X";41.upto(91 ){|c|g=g[2.. -1].gsub(c.chr){g[0,2] }};G=g.spli t(?(); Z=[C[7,10],C[13,76]];U=(0..48).map{[0]*169};O=[];srand(0);q=20;m=40;x=0; Threa d.new {open("/dev/dsp","w"){ |f|50 0.dow nto(0){|k|e=[];300.tim es{|i|e<<(( x=(x+ k**1.9/9e4+0.001)%8)>4?138:118)};f<<e.pack("C*")}}};I=(0..48).map{[0]*169 };9.t imes{ |y|76.times{|x|"1ea8yyjb v4x7d zlzqj sxd8dz4uqjfpb66bq7tu6l wql6vdbds6f 6h60 xz2iglxie44ax1nygtie5t8xpgk2oq00uzj0ucoq2gqc70y9fplfzez0d682syamnhicpwflot4 o9s".to_i( 36)[x+y*76]>0&&I[24+y][4 +x]=1}};-5 00.upto(518){|k|k==1&&s leep(1);k= =q& &(n=rand(11);q+=m;m-=2 ;spawn("espeak","-s",(60+m*2).to_s,"-ven+#{n<7?"m #{n+ 1}":"f#{n-6}"}",["keep",k< 320| |k>360?"ruby":"Austin"," weird"]*32 .c hr));a=[-k,0].max**1.9/ 1e4;v ,z=d=N[[P[1,a/3],Math.sin(Math::PI*a)]];u=N[z==0 ? [0,-1]:z>0?[v,z-1/z]:[-v,1/z-z]] ; n=R[d,u];O.replace(U.map{ |l|l+ [ ]});F.m ap{ |f|a, b,c=f;D [R[S[b,a],S[c,a]],d]>0&&f.size.times{|i|a,b=f[ i], f[i-1];L[J[k,C[D[n,a],D[u,a]]],J[k,C[D [n, b],D[u,b]]]]}};k>0&&(b=M ath. sin( [k,210] .m i n* Math : :PI /15)/36;a=P[1,b*2];y=(30-[k,30].min)/10.0-2.8; E[C[ -1.2,y]*a.conj,(2-k/10%2)*0.06,-1];E[C [-1. 2,y]*a.conj,0.45,-1];E[C [-1. 2,y +1.1]*a, 2. 7 5, b-0. 3]; E[C[-0.6,y+0.5]*a,1.85,b-0.25]);k>=90&&k<210&&2 .tim es{|i|G[(k-90)*2+i].scan(/./){|c|Z[i]+ =[C[ 1,0],C[0,2],C[-1,0],C[0, -2]][c . ord%4]} ;i = k/ 10% 7*8+92 ;U[Z[0]. imag/2][Z[0].real,2]=U[Z[1].imag/2][Z [1]. real,2]=[i,i];r=8;L[J[k,C[-1.2,-2.8] *a.c onj],Z[0]];L[J[k,C[1.2,- 2.8]*a], Z[ 1]];r=0} ; j= 0;k==400&&15.times{|y|65.times{|x|"7gtz whx13 bfmrr9tsr8y0d007qlmygnh47axi9g9v609t cxjuv la0k6y1r96drdisqmfpao411 n6e661l3 zykt bqk p4i33eecq7i2u tfm 2n0bhrviijbr51nwcuhm5ufx3t79a9whf01e3a8kzzepid45ro83 n9r07k xxeht1pycrqo72".to_i(36)[x+y*65]>0 &&U[21 +y][14+x]=88}};s=O.map{| l|i=0;j+ =1;l.m ap{|n|(i+=1)>2& &i<8 3&&k>260&&k<420&&((k-j/6)%80>60||k>320&&k<400&&I[j- 1][i]>0 )&&n=88;a=("%c^_@****"%32)[n%8]; n>7?"%c [%dm%s%c[0m"%[27,30+n/8, a,27]:a} *""};$><<A+"[H"+(0..47).ma p{|i |k+i>517?$s[i].chomp.gsub(32.chr){27.chr+"[44m"+$&+ 27.chr+" [0m"}:s[i]}*10.chr;sleep(0.0 2)};puts }*'');%q{%q.;eval$s=%qev al(%w$s= ("%q.;eval$s=%q$s"+'.gsub(/ 27. chr<<92<<91[0-9]+m/,"")').lines;C=->x,yComplex(x,y) ;P=->r,a Complex.polar(r,a*Math::PI );S=->(( a,b),(c,d))[a-c,b-d];D=- >((a,b), (c,d) )(a*c.conj). re al+b*d;R=->((a,b),(c ,d))e,f=a. rect;g,h=c.rect;[ C[f*d-b*h ,b*g-e*d],e*h-f*g];a=[ ];b=[];6. times|i|a<<[P[1,i/3.0],1] ;b<<[P[2,(i+0.5 )/3.0], 0];F= [a ];6 .t imes|j| F<<[a[i= j-1],b[i],a[j]]<<[ a[j],b [i],b[ j]]<<[b[i],[0,-2],b[j]];J =->k,vk=[k/500. 0,0].min+ 2.5 ;(v/(k+0. 5) +C[k, k/2] )*48;r =0;T=->px,y=p.rect;z =O[ y /2];x>=0&& y>=0 &&z&&z[x]& & z[x ]|=(y%2>1?2:1)|r;L=->p,qs= (p+q)/2;(p-q).a bs<1?(T[s] ;q ):L[L[p,s ], q];N=- >((a ,b)) s=(a.abs2+b*b)**0.5;[a /s, b/s];E=- >p,r,a10 0.times| i|m =-P[r,1.5+i*a*0.02];c,d=(p+ m).rect;(c.abs- d>2||d<-1) && (T[J[0,p+ m] ];T[J[ 0,C[- c, d]]]);A=27.chr;$><<"%q 33.ch r+A[HA [2J";g="NZDD CLYJXM X;YK( OQ'PPYZA5YTZ7M(VOBBSYVXQQ[ SUZV(U:G[NVZ[ZS &V[(YUU(ZT T[ [X'X&Y%Y' ZZ WW[ 'Z&$$[%( '''(&[$(%($(CRGZHZI)D IOZ;IVP Z(SP )[X*DRZCGJJT<<+X I,%% :S=[E== RE&LEXX-'.RMY:(>>U(HU/U[ /[RKOO0Y$1F?LZ% &M@(2NGU3 41R U?+6S2(NV YV AFVR(8FFR YRN4W'NHI@>(EUM6H@Z ISSMS-XL. LLV L?RR8O[OK9B,$%Y[3Y0X ";4 1.upto(91 )|c|g=g[2..-1].gsub(c .chr)g[0,2];G=g .split (?();Z=[C [7 ,10],C [13,76]] ;U=(0..48).map[0] *169;O=[];s r and(0);q=20;m=40;x=0;Thr e ad.newopen( "/dev/dsp","w")|f|5 00.downto(0)|k| e=[];3 00.time s|i|e<<( (x =(x+k** 1.9/9e 4+0.001)%8)>4?13 8:118);f<<e.pa ck("C*");I=(0..48).map[0]*16 9;9.times|y|76 .times|x|"1ea8yyj bv4x7dzlzqjsxd8 dz4uqjf pb66bq 7tu6lwql 6v dbds6f6 h60xz 2iglxie44ax1nygti e5t8xpgk2oq00uzj0 ucoq2gqc70y9fpl fzez0d68 2syam nhicpwfl ot 4o9s".t o_i( 36)[x+y*76]>0&&I[24+ y][4+x]=1;-50 0.upto(518)|k|k==1&&sleep(1) ;k==q&&(n=ran d(11);q+=m;m-=2;spa wn("espeak","-s ",(60+m*2 ).to _s,"-ve n+n <7?"mn +1": "fn-6"",["keep",k<320|| k>360?"ruby" :"Austin","weird"]*32.chr) );a=[-k,0].m ax**1.9/1e4;v,z=d=N[[ P[1,a/3],Math. sin(Math::P I*a) ]];u= N[z= =0? [0,- 1]:z>0?[v,z-1/z]:[-v,1/z-z ]];n=R[d,u] ;O.replace(U.map|l|l+[]) ;F.map|f|a, b,c=f;D[R[S[b,a],S[c,a] ],d]>0&&f.size .times|i|a, b=f[i] ,f[i-1] ;L[J[k, C[D[n,a],D[u,a]]],J[k,C[D[n, b],D[u,b]] ]];k>0&&(b=Math.sin([k ,210].min* Math::PI/15)/36;a=P[1,b*2 ];y=(30-[k,30] .min)/10.0-2.8;E[C[-1.2,y]*a.conj,(2-k/10%2)*0.06,-1];E[C[-1.2,y]*a.conj,0.45,-1] ;E[C[-1.2 ,y+1.1]*a,2.75,b-0.3 ];E[C[-0. 6,y+0.5]*a,1.85,b-0.25]);k> =90&&k<210&&2.times|i|G[(k-90)*2+i].scan(/. /)|c|Z[i]+=[C[1, 0],C[0,2],C[-1,0],C[0,-2]][c.ord%4]; i=k/10%7 *8+92;U[Z[0].imag/ 2][Z[0]. real,2]=U[Z[1].imag/2][Z[1].r eal,2]=[i,i];r=8;L[J[k,C[-1.2,-2.8]*a.conj],Z[0]];L[J[k,C[1.2,- 2.8]*a],Z[1]];r=0;j=0;k==400&&15.time s|y|65. times|x|"7gtzwhx 13bfmrr 9tsr8y0d007qlmygnh47axi9g9v609t cxjuvla0k6y1r 96drdisqmf pao4 11n6 e661 l 3zyktb qkp4i33eecq7i2utfm2n0bhrviijbr51nwcuhm 5ufx3t 79a9whf01e3a8k zzepid 45ro83n9r07kxxeht1pycrqo72".to_i( 36)[x+y*65]>0 &&U[ 21+y] [1 4+x]=8 8;s= O.ma p|l|i= 0;j+= 1;l.map|n|(i+=1)>2&&i<83&&k>260&&k<420& &((k- j/6)%80>60|| k>320 &&k<400&&I[j-1][i]>0)&&n=88;a=("%c^ _@****"%32)[n %8]; n>7?" %c [%dm% s%c[ 0m"%[27, 30+n/8,a,27]:a*"";$><<A+"[H"+(0..47).map |i|k +i>517?$s[ i].c homp.gsub(32.chr)27.chr+"[44m"+$&+27. chr+"[0m":s[i] *10 .chr; sl eep(0.02 ); puts *'');% q%q.;e val$ s=%qeval(%w$s=("%q.;eval$s=%q$s"+'. gsu b(/27.ch r<< 92<<91[0-9]+m/,"")').lines;C=->x,yCompl ex(x,y);P=->r,aC om plex .pola r(r ,a*Ma th::PI); S=- >((a,b),(c,d))[a-c,b-d];D=->((a,b),(c ,d ))(a*c .c onj).real+b*d;R=->((a,b),(c,d))e,f=a.rect ;g,h=c.rect;[C[f*d-b*h,b*g-e*d],e*h-f*g];a=[] ;b= [];6.t imes|i |a<<[P[1,i/3.0],1];b<<[P[2,(i+0.5)/3.0],0];F=[ a ];6. t imes|j|F<<[a[i=j-1],b[i],a[j]]<<[a[j],b[i], b[j]]<<[b[i],[0,-2],b[j]];J=->k,vk=[k/500.0,0].min+2.5;(v/( k+0.5)+C[k,k/2])*48;r=0;T=->px,y=p.rect;z=O[y/2]; x> =0&&y>=0&&z&&z[x]&&z[x]|=(y%2>1?2:1)|r;L=->p, qs=(p+q)/2;(p-q).abs<1?(T[s];q):L[L[p,s],q];N=->((a,b))s=(a.abs2+b*b)**0.5;[a/s,b/s];E=->p,r,a100.times|i|m=-P[r,1.5+i *a*0.02];c,d=(p+m).rect;(c.abs-d>2||d<-1)&&(T[J [0,p+m]];T[J[0,C[-c,d]]]);A=27.chr;$><<"%q33.chr+A[HA[2J";g="NZDDCLYJXMX;YK(OQ'PPYZA5YTZ7M(VOBBSYVXQQ[SUZV(U:G[NVZ[ZS&V[(YUU(ZTT[[X'X&Y%Y'ZZWW['Z&$$[%('''(&[$(%($(CRGZHZ I)DIOZ;IVPZ(SP)[X*DRZCGJJT<<+XI,%%:S=[E==RE&LEXX-'.RMY:(>>U(HU/U[/[RKOO0Y$1F?LZ%&M@(2NGU341RU?+6S2(NVYVAFVR(8FFRYRN4W'NHI@>(EUM6H@Z}}.gsub(/#{27.chr<<92<<91}[0-9]+m/,"")