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

Cookpad Spring 1day internship 2018 超絶技巧プログラミングコース資料

Cookpad Spring 1day internship 2018 超絶技巧プログラミングコース資料

Yusuke Endoh

February 27, 2018
Tweet

More Decks by Yusuke Endoh

Other Decks in Programming

Transcript

  1. 4

  2. 超絶技巧プログラミングで得られるもの • コンピュータ科学の理論を実践する体験 – ×「才能の無駄遣い」 – 〇「コンピュータ科学 50 年の歴史の無駄遣い」 •

    知らない技術に触れるきっかけ • ふつうには出会わない新鮮な制約・価値観 • プログラミング言語の無限の可能性
  3. 今日の流れ • 午前:講義 – 超絶技巧プログラミングのテクニックを駆け足で学ぶ • 12時~13時:昼食 • 13時~16時:実習 •

    16時~:発表会 – 作ったプログラムをお互いに紹介しあう • うまくできたらコンテストに投稿を! – TRICK FINAL(締切:2018/03/31)(遠藤が運営メンバ) – IOCCC25(締切:2018/03/15 03:08:07 UTC) ここで 15 分くらい?
  4. Quine-relay eval$s=%q(eval(%w(B=92.chr;g=32.chr;puts(eval(%q(N=10.chr;n=0;e=->s{Q[Q[s,B],?"].K(N,B+?n)};E=->s{'("'+e[s]+'")'};d=->s,t=?"{s.K(t){t+t}};def~f(s,n)s.K(/.{1,#{n*255}}/m){yield$S=E[$s=$&]}end;Q=->s,t=?${s.K(t){B+$&}};R=";return~0;";V=-> s,a,z{s.K(/(#{B*4})+/){a+"#{$&.size/2}"+z}};C=%w(System.Console~Write);$C=C*?.;$D="program~QR";$G="~contents~of"+$F="~the~mix!g~bowl";$L="public~static";rp=->s,r{v="";[r.!ject(s){|s,j|o={};m=n=0;s.size.times{|i|o[f=s[i,2]]||=0;c=o[f]+= 1;m<c&&(m=c;n=f)};v=n+v;s.K(n,(j%256).chr)},v]};%(fn~mX{Z`x21("{}",#{E["object~QR~extends~App{#{f(%((display~"#{e[%(Zf("1d;s/.//;s/1/~the~sum~of~a~son~and0/g;s/0/~twice/g;s/2/`x59ou~are~as~bad~as/g;s/3/~a~son`x21Speak~your~m!d`x21/g^n# The~Relay~of~Qu!e.^n#Ajax,~a~man.^n#Ford,~a~man.^n#Act~i:~Qu!e.^n#Scene~i:~Relay.^n#[Enter~Ajax~and~Ford]^n#Ajax:^n#");function[]=f(s);for~i=1:2:length(s),Zf("2%s3",part(dec2b!(hex2dec(part(s,i:i+1))),$:-1:2)),end;endfunction`n#{s,v=rp ["Transcript~show:~'#{d["Z"+E[%(fun~p~n=Z(Int.toSJ~n`x5e"~");p~0;p~0;p~130;List.tabulate(127,p);SJ.map(fn~c=>(p(3+ord~c);Z"-1~0~";c))#{E[%(puts~"#{Q[e[%(echo~'a::=`x7e#{Q[Q["let~s=#{E["!t~mX{Z#{d[E[%(module~QR;!itial~beg!~#{f("let~s=#{ E[%(Module~QR:Sub~MX:Dim~s,n,i,c~As~Object:n=Chr(10):For~Each~c~!"#{d["<?xml#{O="~version='1.0'"}?><?xml-#{I="stylesheet"}~type='text/xsl'href='QR.xslt'?><xsl:#{I+O}~xmlns:xsl='http://www.w3.org/1999/`x58SL/Transform'><xsl:output~metho d='text'/><#{U="xsl:template"}~match='/'><`x21[CDATA[#{%(sub~f(s$,n)Z(s$);:for~i=1to~n~Z("Y");:next:end~sub:f("#{V[e[%(H,format="#{y="";f("^H{-}{txt}{#{Q["echo~-E~$'#{Q[Q[E[%(with~Ada.Text_Io;procedure~qr~is~beg!~Ada.Text_Io.Put("#{d[% (!terp:library"afnix-sio"`ntrans~O(n){trans~o(afnix:sio:OutputTerm)`no:H(Byte(+~128~n))}`ntrans~f(v~n){`nO(+(/~n~64)107)`nO(n:mod~64)`nO~v}`ntrans~D(n){if(<~n~4){f(+(*~6~n)9)48}{if(n:odd-p){D(-~n~3)`nf~27~48`nf~36~11}{D(/~n~2)`nf~21~48 `nf~48~20}}}`ntrans~S"#{e[%W[STRINGz:=~226+~153,a:=z+~16

    6,b:=a+"2 "+z+~160,c:=b+"8"+z+~165,t:="#!clude<iostream>"+~(10)+"!t"+~(32)+"mX{puts#{d[E[%(class~QR{#$L~void~ma!(SJ[]v){System.out.Z(#{E["H('#{Q[e["implement~ma!0()=Z"+E["BEGIN{ Z#{E[%(echo~'#{%(f(s){System.out.Z(s);}s="389 **6+44 *6+0 0p45*,"; for(c:#{E[(s="#!clude<iostream>`n!t~mX{std::cout<<#{E[%(class~Program{#$L~void~MX{#$C("Qu!e~Relay~Coffee.^n^nIngredients.^n");for(!t~i=9;i++<126;)#$C($"{i}~ g~caffe!e~{i}^n");#$C("^nMethod.^n");foreac h(c h ar~c~!#{E[%((doseq[s(lazy-cat["IDENTIFICATION~DIVISION.""PROGRAM-ID.~QR.""PROCEDURE~ DIVISION."'DISPLA`x59](map~#(str"~~~~^""(.replace~%1"^""" ^"^"")"^"&")(re-seq~#".{1,45}""#{e["(f=(n )- >Array(n+1).jo!~'Y');console.log('%s',#{V[E[%((H-l!e"#{e["impor t~std.stdio;void~mX{H(`x60#{%(method~MX{Z(@"#{d[" [#{%(class~QR:Application{void~f(SJ~con st~s,!t~n){for(Pr!t(s);n;n--)Pr!t("Y");}void~MX{#{f("IO.puts "+E[%((pr!c~"#{e["`nma!(_)->`nio:fH#{d[E['Zf n("""'+d[?"+"%option~noyywrap`n%%`n%%` n!t~mX{puts#{E["echo~'#{Q[Q[%(~:~A~."#{g*9}"~;~:~ B~A~."~WRITE(*,*)'"~A~;~:~C~B~T`x59PE~." ~'"~CR~;~:~D~S"~#$D"~C~S^"~Z~^"(&"~C~ S^"~#{e[%(Z"#{e["s:=OutputTextUser();Write All(s,#{E[%(Zf"#{e[d[f('set~Z"-";Z'+E [%(package~ma!;import"fmt";func~mX{ fmt.Pr!t#{E[%(236:j;{119:i;{206i-:i;.48<{ 71+}{[i]^48-*}if}%}:t;"algoritmo~Q R;!"[195][173]++'cio~imprima("'"0 1314 1"t"/12131"t~6*"/1:1918151:??62714 13/4=3626612/2 /353251215/`x5a0`x5a0R"t"#{e[%( show~"z=new~java.util.zip.G`x5aI POutp utStream(System.out);z.H('#{ "ma!=putStr"+E["class~QR{#$L ~function~mX{neko.Lib.Z#{E[%(p rocedure~mX;i:=c:=0;s:=#{E[%(.c lass ~public~QR`n.super~#{$T="ja va/io/Pr!tStream"}`n.method~#$L~ma!([L #{S="java/lang/S"}J;)V~;]`n. limit~stack~2`ngetstatic~#{S}ys tem/out~L#$T;`nldc~"#{ e[%(class~QR{#$L~void~ ma!(SJ[]v){SJ~c[]=new~SJ[99999],y="",z=y,s=" #{z=t=(0..r=q=126).map{|n| [n,[]]};a="";b=->n{a<<(n%78+55) %84+ 42};(%(P={0:'[+[]]',m:'((+[])'+(C= "['constructor']" )+"+[])['11']"};for(R~!~B=('`x21[]@`x21`x21[]@[][[ ]]@'+(A="[]['fill']")+"@( []+[])['fontcolor']([])@(+('11e20 ')+[])['split']([])@"+A+C+"('return~escape')()("+ A+')').split( '@'))for(E~!~D=eval(G='('+B[R]+'+[])'))P[T=D[E]]=P[T]| |G+"['"+E+"']";for(G='[ ',B=0;++B<36;)P[D=B.toSJ(36)]= B<10?(G+='+`x21+[]')+']':P[D]||"(+('"+B+"'))['to'+( []+[])"+C+"[ 'name']]('36')";A+=C+"('console.log(unescape(^"";for(E~!~G =#{E[%(A=Z;A("echo~'k` x60");[(A("`x60`x60s"`x5e8* "i");for~j=6:-1:0;x=(Int(c)>>j)%2+1;A("`x60"*"kki"[x:x+1 ])end)fo r~c~!~jo!(["Section`x48eader+name:=QR;SectionPublic-ma!<-(";[ "^"$(replace(replace( s,"Y","YY"),"^"","Y^""))^" .Z;"for~s=matchall(r".{1,99}",#{Q[E["console.log"+Q[E[%(@s=g loba l[#{i=(s=%(`x48AI~1.2`nVISIBLE~"#{"x=sJ.K(#{V[E["changequote(<@,@ >)`ndef!e(p,<@#{"all :`n`t@echo~'#{d["l!el:99 999;Z#{E["solve~satisfy;output~[#{E[%(.assembly~t{}.method~#$L~ vo id~MX{.entrypo!t~ldstr"#{e["m{{`x21:~x`nqr:~|-`n~:db`x60#{e[s="$Z#{E[%(#!clude< stdio.h>`nmodule~QR{ }implementation{!t~mX_ _attribute__((C,spontaneous)){puts#{E["Zf#{E["echo"+E["#import<stdi o.h>#{ N}!t~mX{puts#{E["Z_sJ"+E["s=toascii#{E["Z#{E["$console:l!e[#{"# $D(output);beg!~H(# {f((p="eval";%($_="#{ s,v=rp["$_='#{Q[%(<?php~$z=3+$w=strlen($s=#{Q[E["!t~mX{H#{E["(#{?_*11} )dup~=/s(|~~~~~.~~~|)def(#{Q["qr:-H('#{Q[e["!it{#{f (%(Z('cat("')`nfor ~c~!"".jo!(["echo~'s ay~''%s'''^n"%l~for~l~!#{E[d[d["eval$s=%q(#$s)",?'],?']]}.split("^n")]): Z('r=fput(char(%d))'%ord(c))`nZ('end^n")')#),6 ){"Zf#{d[$S,?%]};" }}}"],?']}').",B]}) {9~7{exch~dup~1~and~79~mul~32~add~exch~2~idiv~3~1~roll~s~exch~2~!dex~exch~p ut~1~sub~dup~6~eq{1~sub}if}repeat~s~=~pop ~pop}forall~=~quit "]+R}}"]]})*3;echo" ^x89PNG^r^n^x1a^n";$m="";$t="^xc0^0^xff";for($i=-1;++$i<128*$z;$m.=$c--?($w- $c||$i>$z)&&$i/$z<($c<$w?ord($s[(!t)( $c/3)]):$c--%3+2)? $t[2].$t[$c%3%2].$ t[$c%3]:"^0^0^0":"^0")$c=$i%$z;foreach(array("I`x48DR".pack("NNCV",$w+2,128,8,2 ),"IDAT".gzcompress($m),"IEND")as$ d)echo~pack("NA*N ",strlen($d)-4,$d, crc32($d));).K(B,"`x7f"),?']}';s:g/^x7f/Y/;Z~$_",128..287];s="$_='#{Q[s,c=/['Y]/ ]}';$n=32;$s='#{Q[v,c]}';$s=`x7 es{..}{$a=$&;$b=c hr(--$n&255);`x7e s/$b/$a/g;}eg;Z";(s+N*(-s.size%6)).unpack("B*")[0].K(/.{6}/){n=$&.to_i~2;((n+14)/2 6*6+n+47).chr}}";s|.|$n=ord $&;substr~unpack( B8,chr$n-!t($n/32 )*6-41),2|eg;eval~pack'B*',$_).scan(/[~,-:A-z]+|(.)/){p="s++#{$1?"chr~#{$1.ord}+e": $&+?+};"+p};p),1){"'#$s' ,"}}'')end.".K(/[: ;()]/){?`x5e+$&}} ]"]};quit"]};t=num2cell(b=11-ceil(s/13));for~n=1:9m={};for~i=1:141f=@(x,y,n)repmat ( ['Ook'~char(x)~'~Ook' ~char(y)~'~'],[1~a bs(n)]);m(i)=[f(z =46,63,n)~f(q=z-(i<13)*13,q,i-13)~f(33,z,1)~f(63,z,n)];end;t(x)=m(diff([0~s(x=b= =n )])+13);en d;Zf ('%%s',t{:})"]]+R} }"]]}`n"]};return~ 0;}~})]};"]}`x60` n~global~_start`n~_start:mov~edx,#{s.size}`n~mov~ecx,m`n~mov~ebx,1`n~mov~eax,4` n ~!t~128`n~mov ~ebx,0`n~mo v~eax,1`n~!t~12 8`nx:~|`n~}}{{{qr}} }"]}"call~void~[ms corlib]#{C*"::"}(sJ)ret})]}];"]};quit();",?$].K(?'){"'^''"}}'"}@>)`np"],?&,?& ] },'&(%d+)&',fu nction(s)retur n~sJ. rep('Y',tonu mber(s))end);Z(x)". K(/[:"]/,":^0")}"` n`x4bT`x48`x58B`x59E~B`x59E)).size+1}x~i8]c"#{s.K(/[^"`n`t]/){"^%02`x58"%$ &. ord}}^00"declare~i32@puts(i8*)d ef!e~i32@mX{ %1=call~i 32@puts(i8*getelemen tptr([#{i}x~i8],[#{ i}x~i8]*@s,i32~0,i32~0))ret~i32~0})],?#]]]})];");"],"^n")];[for~i=0:2:4; x=(( Int(c)%83-10)>>i)%4+1;A("ski`x60 "[x:x])end~for~c ~!"AG- `x48-`x48Fy.IlD==;=jd lAy=;=jldltldltl{lAu lAy=jtlldlAyFy=?=jdlAyGFyFyG2AFy>zlAFFBCjldGyGFy>GFy.AGy=G==n`x48==nl ldC=j@=j tlldltldlAut11"];A("'"))]})A+="' +`x21[]+'"+G.charCo deA t(E).toSJ(16);for(A+=" ^".replace(/'+`x21[] +'/g,^"%^")))')()",R=0;R<9;R++)A=A.replace(/'.*?'/g,function(B){T= [];for(E=1 ;B[E+1];)T.push(P[B[E++]]);return~T.jo!('+')});conso l e.log('"'+A+'"'))).byte s{|n|r,z=z[n]||(b[r/7 8];b[r];q<6083&&z[n]=[q+=1,[]];t[n])};b[r/78];b[r]}";!t~i=0,n=0 ,q=0;for(;++n< 126;)c[n]=""+(char)n;for(;i<#{a.size};){q=q*78+(s .charAt(i)-13)%84;if(i++ %2>0){y=q<n?c[q]:y;c[n ++]=z+y.charAt(0);System.out.Z(z=c[q]);q=0;}}}})]}"`n!vokevi rtual~#$T/Zln(L#{S }J;)V`nreturn`n.end~method)+N]};H("DO,1<-#"|| *s);s?while~t:=ord(move(1) )do{i+:=1;u:=-i;every~0t o~7do{u:=u*2+t%2;t/:=2};H("PLEASE")^(i%4/3);H("DO,1SUB# "||i||"<-#"||((c-u)%2 56));c:=u;};H("PLEASEREADOUT,1^nPLEASEG IVEUP");end)]};}}"].tr(?"+B ,"`x21`x7e")}'.tr('`x7e`x 21','YY^u0022')as~byte[]);z.close()"`n)]}"{"W""w"@j ~1+:j^-~118%1+*}%"/35512 416612G61913@921/17A331513"t'") ;fim')]};})],61){"Zn#$S`n"},? %]]}"`nquit)]});CloseStream (s);QUIT;"]}")]}"~DUP~A~."~DO~10~I=1,"~.~CR~S "~&A,&"~C~."~10~~~~~~CONTINU E"~CR~S^"~&A)^",&" ~C~0~DO~B~."~&char("~COUNT~.~." ~),&'"~CR~LOOP~S^"~&^"^""~C~S "~end~#$D"~C~A~."~STOP"~CR~A~."~END"~CR ~B`x59E~;~D~),B],?`x21].K(?',%('"' "'))}'"]};}".K(?"){'"34,"'}.K(N){ '"10,"'}+?",?%]+'~""")'],?`x7e] }."]}"))],15){"f(#{V[$S[1..-2] ,'",',');f("']},0);"}}}})}]pq"]}");})} `x60);}"]}"))].K(?`x60,"Yx60"),'#{f (',')}']})"]}"))["~~~~^"~^".""STO P~RUN."])](Zln( str"message(STATUS~^"~~~~~"(.replace(.replac e(str~s)"Y""YY")"^"""Y^"")"^")")))).re verse]})#$C($"Put~caffe!e~{(!t)c}~!t o#$F.^n");#$C("Liquify#$G.^nPour#$G~!to~the~bak!g~ dish.^n^nServes~1.^n");}})]};}/****//**** /";t={};b="";L="";n=i=0;D=->n{L<<(n+62) %92+35;D};s.bytes{|c|n>0?n-=1:(t[c]=(t[c]||[]).reject{|j| j<i-3560};x=[];t[c].map{|j|k=(0..90).f!d{|k|n ot~s[i+1+k]==s[j+k]}||91;k>4&&x<<[k,j]};x=x. max)?(n,j=x;x=b.size;(u=[x,3999].m!;D[u%87][u/87];L<<b[0,u];b[0,u ]="";x-=u)while~x>0;x=4001+i-j;D[x%87][x/87][n-5] ):b<<c;t[c]+=[i+=1]};"#!clude<stdio.h>`nchar*p=#{E [L]},s[999999],*q=s;!t~mX{!t~n,m;for(;*p;){n=(*p-5)%92+(p[1]-5)%92*87;p+=2;if(n >3999)for(m=(*p++-5)%92+6;m--;q++)*q=q[4000-n];else~for( ;n--;)*q++=*p++;}puts(s)#{R}}")]}){s+="00g,";for(m=1;m<256;m*=2)s+="00g,4,:"+(c/m%2>0?"4+":"")+",";f(s);s="4,:,";}f(s+s);for(c:Base64.getDecoder().decode("kaARERE`x58/I0ALn3n5ef6l/Pz8+fnz58/BOf5/7/hE`x58/O`x5azM5mC`x58/Oczm`x5azBPn5+`x 58/OczMznBL/nM5m`x5azBPu++fPPOc5zngnnO`x5azO`x5agnBMGAW7A==")){c=c<0?256+c:c;for(i=0;i++<3;c/=8)f(c%8);f("8*+8*+,");}f("@");).K(?',%('"'"'))}'|sed~-e's/Y/YY/g'~-e's/"/Yq/g'~-e's/.*/Z~"&"^nquit/')]}}"]],?']}');".K(B,?`x5e)]}.replace("`x 5e","Y"));}})]]};}";FORiTO`~UPBtDO`~INTn:=ABSt[i];Z(~(50+n%64)+c+~(50+n%8MOD8)+c+~(50+nMOD8)+b+"`x4a"+a)OD]*"REPR"]}"`ntrans~c~0`ndo{D(Integer(S:get~c))`nf~35~39}(<(c:++)(S:length))`nf~24~149)].K(N,'"&Character'+?'+'Val(10)&"')}");end; )]+"`nsys.exit~0",B],?']}'",/[^{}]/]}}",35){y<<",`n"+$S;"%s"}}")+y],'",','):f("']}",0))}]]></#{U}></xsl:#{I}>"].K~N,'"&~VbLf~&"'}":s="~~~":For~i=0To~7:s~&=Chr(32-(Asc(c)>>7-i~And~1)*23):Next:#$C(s~&n~&Chr(9)&n~&"~~"):Next:#$C(n~&n~&n): End~Sub:End~Module)]}`nput=s`nZ`nqa`x21",3){%($H("%s",#$S);)+N}}end~endmodule)],?%]+R}}"]},i=0,t='k';while(s[i])t='^x60.'+s[i++]+t;console.log(t)",B],?`x21].K(?',%('"'"'))}'"^n::=^na")],/[`[`]$]/]}")]};Z"0~0~-1";)],?']}';cr",127..255]; f(%(variable~s=`x60#{s.K(/.{1,234}/){$&.K("`x60",%(`x60+"`x60"+`x60))+"`x60+`n`x60"}}`x60,i;for(i=0;i<129;i++)s=strreplace(s,pack("C",255-i),substrbytes(`x60#{v[0,99]}`x60+`n`x60#{v[99..-1]}`x60,i*2+1,2));Zf("%s",s)),7){"f('%s')`n"%$s. unpack("`x48*")}}Zf("^n#[Exeunt]");quit)]}")),196){%(Z#$S;)}}}"]});})).gsub(/[!HJKXYZ^`~]/){[B*2,:write,B,:tring,:gsub,"ain()",B*4,:print,g,:in][$&.ord%47%12]})))*"")#_buffer_for_future_bug_fixes_#_buffer_for_future_bug_fixes_#_buffer_ ############################################################################## Quine Relay -- Copyright (c) 2013, 2014 Yusuke Endoh (@mametter), @hirekoke #############################################################################)
  5. Quine-relay • A Ruby code • that generates Rust code

    • that generates Scala code • … • that generates REXX code • that generates the original Ruby code 128 languages involved in total
  6. Quine-relay • A Ruby code • that generates Rust code

    • that generates Scala code • … • that generates REXX code • that generates the original Ruby code 128 languages involved in total
  7. 14

  8. 15

  9. mquine.rb 16 eval(_=%[b='DEILMQTVY';eval((%[a=(-1)EE0.5;f=->EfVf.each_slice(2)Y;c=->wVz=->dVd.mapVd=d.rotate(1)YY ;Q=->k,l,mV((m-k)E(l-k).conT).arQ<0Y;y=[];x=0.99;o,T=w.partitionV|n|d=0;z[n].mapV|k,l|y<<f[k,x,k,1,l ,1,l,x];d+=k.conTElY;d.arQ<0Y;f[o,T,[[0,d=2IEa,d+15,15]],o.map(Dd=:reverse),T.map(Dd),[]].mapV|o,T|T .mapV|h|z[h].max_byV|u,|u.realY;Y.sort_byV|i,|-i.realY.mapV|h|i,=h;v=0;o.mapV|n|z[n].mapV|x|m,l,E,k= x;e=(i-m).arQEE2;v<eDD(d=Q[k,m,l])^(Q[k,m,i]^d|(Q[m,l,i]^d))DDo.allMV|n|z[n].allMV|k,l|[i,m,k,l].uni q.size<4||Q[i,k,l]==Q[m,k,l]||Q[i,m,k]==Q[i,m,l]YYDD(v=e;w=n;T=Ex,m,Eh,i)YY;w[0..-1]=TY;o.mapV|v|t,= s=z[v];n=->rVk,m,l=r;k=k[2],l,m[2];r[I]=Q[Ek]DDv.allMV|q|z[k].anyMV|k,l|q==k||Q[k,q,l]YYY;z[s].mapV| k,l,m|l[0,2]=k,m;n[l]Y;(s[I..-1].mapVt=t[1]until(t[I]);k,m=l=t;m[0],k[1]=t;n[m];n[t=k];lY<<t).mapV|k

    ,m,l|y<<f[k[2],x,l,x,m[2],x]YY;x=1Y;yY;e=0;%[`^Tx52t<^cd,7/w(kabvbEz5arIwIa17.=c'slxr=-'4|e)EwkMI,_^ pvMVhsnME.rLw_k)^tp>+TIEduE45u>mv%^Y=Vny-`zce)k`heIt%`Vzf;c2nk4d|Vp^D_,,|kDDL2r_sDy%%fiMV6cYE)5`,m/k YQ/;IEezMVv,QchILY|p%%i<vstDt)=M7vLcT>=4Q2(vwael61//<ck>-l67uQ;2Tq,c_'qEIcm1cL;i++2-tYdbenq%pxr;2'Vn (uDa)n)zf4w)%5vh;ssV5kI;)z;2=+Toe<VL_D0`VLu;ook_y+eT`>IeT9-(i<MiVdd)ib_y+x`s^_u>M1s/mYQvEY`vMxu%Y0u5 7Qaoh2<Mkd'vtkp^zTc`E->Ep+icop_u0%=-zv,omq`Qz/41DV'`f9L5`M'bVxx%/;qLtq12%q:V'9,fD,ovu%qr|+e+rudI`Ir0 5chVd+Q5`II76rY0laT%b(I>Y%EQ1xf^|r,1)%4--zQa'<qxL-7Y0+|'vvbIxso0usv;%.I:pLQbe5a),Vu|91(0EIv^T>c5Dmd: 9-I15%Lp/>>z57^,Th2>%la0;5`dE1<xvrd09^9zz<.t,LpofrTTsQi'u5;Lwp7+zmm`'>qy;f6)||Ikw_0wdMM5<hmn64wbQ_rD m'>so7b..4qy`nQrz%Vf7Ii^epY(x=|49Lh(=>sI_sbofb7|qM,unaD%^i:|;_tEEnb-DDt`t%I2h;0x5f^yhs,pbLf+m^e>yqzQ '%::|^=,5-b=^_1x1se`kp,%wq4T%;'E.:Dsp_V-0||,)=;.a|<%0QY:;t:fEmk:4|_%o-.:aooq/6mThdvz4`uQqY1r'em.5'z1 2p7e%%pp6ebMM,m`5QpYx'd`,`6a4T)6Q.k.E.YsdiE^ox9pyrsr%|(kfn=y9q`6;=V<z%9(0cf^yp=:Irw-c/y>%iie%)y-1i(y 'V-n^uTva%l0Q>,yz;E0:LbV'eTb6MIb``Da.__ihbacxY|fc6>pTtl;ivVt,q>/%w,=hnI+i90>10u59te,Ildw4p94x`iwvs`f +^)w1M>%wf^].bytesV|i|e=eE59+(i-5)%L9Y;Q=->iVk=e%i;e/=i;kY;d=VI2=>c[[]]Y;54.upto(1I0)V|h|d[h%L9+I7]= c[(0..Q[5]).mapVl=o=T=[];n=0;(-2..Q[17]).mapV[l=Q[2],o=Q[1I]+Q[21]Ea+1+a]Y.flat_mapV|m,n|E,(h,)=[[o, l],[(o+o=n)/2,0]][0..lDl=m]Y.mapV|o,l|n=l<1M((n==0ML:1).upto(L)V|k|T<<h+kE(n-h)/4+kEkE(o-2En+h)/64Y; h=o;0):oY;TY]Y;n=[];m=0;v=aEE0.04;z=15/v.arQ;w=-0.2I;h='eval(_=%['+_+'])';h.tr(b,']+b+%[').bytesV|o| q=-w+s=wEm+=1;r=vEp=vEEmEz;d[o].mapV|v|n<<v.mapV|v,l|T,k=v.rect;[(p+(r-p)ET/=15)El,q+wET-k]YY;m<101D Dn+=[f[p,q,r,s,E[r,0]E(m/100),r,2,p,2],f[p,2,r,2,k=rET=0.976,2,TE=p,2],f[T,2,k,2,k,x=-715,T,x],f[T,x ,k,x,r,x,p,x],f[p,x,r,x,r,s-l=690,p,q-l,E[p,x+2]E(1/m)]];Y;T=VY;k=VY;l=''<<I2;m=n.mapV|i|(p,q),(r,s) ,(t,u)=Ei;p-=r;r-=t;Mf+l+i.mapV|m|[[T,:v,Em],[k,:vn,(rE(q-s)-pE(s-u))Ea,(p.conTEr).imaQ]].mapV|T,o,p ,w|T[[o,E(p.rect<<w).mapV|p|(pE500).round/z/10Y]El]||=T.size+1YE'//'YElY;o=''<<I5;puts(%(Q%squine')% l,o+%V'+(eval(%[Y+h+%V]);exit);'Y,T.keys,k.keys,m,o+M');]).tr(b,'%)27>fiz|'.tr('x%-|','%-'<<125)));' [[[ Monumental Quine (c) 2015 Yusuke Endoh -- tested with ruby 2.2.1 -- built on 2015/04/01 ]]]'])
  10. rquine.rb : 宇宙線耐性 Quine 19 eval=eval=eval='eval$s=%q(eval(%w(puts((%q(eval=ev al=eval=^Z^##^_/#{eval@eval@if@eval)+?@*10+%(.size >#{(s=%(eval$s=%q(#$s)#)).size-1}}}#LMNOPQRS_##thx .flagitious!## )+?@*12+%(TUVW

    XY/.i@rescue## /_3141592653 589793+)+?@* 16+%(+271828 182845904; _987654321 0;;eval)+? @*18+%("x =((#{s.s um}-eval. _sum)%256 ).chr; ;eval)+?@ *12+%(.s can(//){ a=$`+x+$ ^_a.unpa ck (^ H*^)[0]. hex%999989==#{s.unpac k("H*")[0].hex%999989 }&&eval(a)}#"##"_eval @eval####@(C)@Copyrig ht@2014@Yusuke@Endoh@# ###)).tr("@_^",32.chr< <10<<39).sub(?Z,s));e xit#AB CDEFGHIJK)*%()))#'##' /#{eval eval if eval .size>692}}#LMNOPQRS ##thx.flagitious!## TUVWXY/.i rescue##/ 3141592653589793+ +271828182845904; 9876543210;;eval "x=((42737-eval. sum)%256).chr;;eval .scan(//){a=$`+x+$' a.unpack('H*')[0].hex%999989==68042&&eval(a)}#"##" eval eval#### (C) Copyright 2014 Yusuke Endoh ####
  11. 実行 (1) 20 $ ruby rquine.rb > rquine2.rb $ diff

    -s rquine.rb rquine2.rb ファイル rquine.rb と rquine2.rb は同一です
  12. broken.rb (適当に1文字消した) 21 val=eval=eval='eval$s=%q(eval(%w(puts((%q(eval=ev al=eval=^Z^##^_/#{eval@eval@if@eval)+?@*10+%(.size >#{(s=%(eval$s=%q(#$s)#)).size-1}}}#LMNOPQRS_##thx .flagitious!## )+?@*12+%(TUVW XY/.i@rescue## /_3141592653

    589793+)+?@* 16+%(+271828 182845904; _987654321 0;;eval)+? @*18+%("x =((#{s.s um}-eval. _sum)%256 ).chr; ;eval)+?@ *12+%(.s can(//){ a=$`+x+$ ^_a.unpa ck (^ H*^)[0]. hex%999989==#{s.unpac k("H*")[0].hex%999989 }&&eval(a)}#"##"_eval @eval####@(C)@Copyrig ht@2014@Yusuke@Endoh@# ###)).tr("@_^",32.chr< <10<<39).sub(?Z,s));e xit#AB CDEFGHIJK)*%()))#'##' /#{eval eval if eval .size>692}}#LMNOPQRS ##thx.flagitious!## TUVWXY/.i rescue##/ 3141592653589793+ +271828182845904; 9876543210;;eval "x=((42737-eval. sum)%256).chr;;eval .scan(//){a=$`+x+$' a.unpack('H*')[0].hex%999989==68042&&eval(a)}#"##" eval eval#### (C) Copyright 2014 Yusuke Endoh #### e
  13. 実行 (2) 22 $ ruby broken.rb > rquine2.rb $ diff

    rquine.rb rquine2.rb ファイル rquine.rb と rquine2.rb は同一です どの 1 文字を消しても元に戻ります 壊れているのに元のプログラムを出力した!
  14. プログラムのアスキーアート化 • 好きなプログラムを書く – 空白は使わない – 改行も使わない – ¥ も使わない

    • おまじないで囲む p 42 p(42) p(1) p(2) p(1);p(2) puts("¥¥") puts(92.chr) eval(%w( puts("Hello,world!") ).join) この範囲を自由に整形可能
  15. プログラムのアスキーアート化 • 好きなプログラムを書く – 空白は使わない – 改行も使わない – ¥ も使わない

    • おまじないで囲む p 42 p(42) p(1) p(2) p(1);p(2) puts("¥¥") puts(92.chr) eval(%w( puts("Hello,world!") ).join) この範囲を自由に整形可能 eval(%w( p u t s ( " H e l l o , w o r l d ! " ) ).join)
  16. 解説 • %w(foo bar) は 文字列の配列 ["foo", "bar"] を返す •

    Array#join は文字列を結合して返す – 空白や改行が取り除かれる • eval は文字列を Ruby コードとして実行する eval(%w( p ( 1 ) ).join) #=> 1 が出力される %w( p ( 1 ) ).join #=> "p(1)" %w( p ( 1 ) ) #=> ["p","(","1",")"]
  17. 実習(10分) • 自己紹介を出力するプログラムを イニシャル形状にしてみましょう – 元プログラム↓ – 余分は # や

    ; などで埋める – 自己紹介やイニシャルではなく、好きなメッセージや 形状でも構いません eval(%w( puts("Yusuke-Endoh,hobby:walking") ).join) eval(%w( pu ts ("Yusu Ke -E nd oh,h obby:w al ki ng ") ###### ## ).join) eval(%w(puts("YusuKe -E nd oh,h ob By :w alki ng")## ### ##### ## #### ###### ###### #### ## ## ## #############).join)
  18. 発展問題の解答例 • ¥ は %w(…) がエスケープとして消費する – %w(puts("¥¥")).join は puts("¥")

    になる – 宿題:%w(puts("¥¥¥¥")).joinにすればOK? • "foo¥nbar" は "foo#{ 10.chr }bar" と 書き換えられる – 各文字には、対応する数字(codepoint)がある • 調べ方→ – 他の書き換えは宿題 p "¥n".ord #=> 10 p 10.chr #=> "¥n" ここで 1 時間くらい?
  19. ターミナルで色 • エスケープシーケンスを print することで ターミナルを制御できる – 色を変えたり、カーソルを移動したり • "¥e[数字m"

    で色を変えられる – 色以外にもいろんな属性がある (ANSI エスケープシーケンスで検索) puts "¥e[34mfoo¥e[0m" #=> foo(青字) puts "¥e[44mfoo¥e[0m" #=> foo(青地) 30黒 31赤 32緑 33黄 34青 35紫 36水 37白 40黒 41赤 42緑 43黄 44青 45紫 46水 47白
  20. ターミナルでアニメ • アニメの基本:繰り返し端末に print する – アスキーアートを見せる→少し待つ →アスキーアートを見せる→少し待つ→…の繰り返し – print

    と sleep を繰り返すだけでも良いが エスケープシーケンスを使うとより見やすくなる • アニメに役立つエスケープシーケンス – "¥e[H" でカーソルをホームに移動 – "¥e[J" で画面の文字を全消去 • 正確には、カーソル位置より後にある文字を消去
  21. アニメの例 • 最初にターミナルをクリアする • ホームに戻って puts – を繰り返す – ポイント:画面のクリアは最初だけ

    (毎回やるとちらつく) print "¥e[H¥e[J" loop do print "¥e[H" puts "<--+" puts " |" puts " " sleep 0.5 print "¥e[H" puts "+-- " puts "| " puts "V " sleep 0.5 print "¥e[H" puts " " puts "| " puts "+-->" sleep 0.5 print "¥e[H" puts " ^" puts " |" puts " --+" sleep 0.5 end <--+ | +-- | V | +--> ^ | --+
  22. 実習(10分) • 波々なアニメプログラムを書いてみましょう – 土台→ • 波に色を つけて みましょう •

    発展:このプログラムをアスキーアート化してみましょう – ヒント:"¥e" を避ける必要がある W, H = 60, 20 def print_sine_curve(phase) s = (0..H).map { " " * W } W.times do |x| y = Math.sin((phase+x)/W.to_f*2*Math::PI) s[((y + 1) * H / 2).round][x] = "o" end puts s.join("¥n") end print_sine_curve(0) # <= ここの数字を変えてみる
  23. 解答例 • 波々アニメプログラム→ • 波に色をつける↓ • 発展問題は宿題("¥e" は 27.chr) phase

    = 0.0 print "¥e[H¥e[J" loop do print "¥e[H" print_sine_curve(phase) phase += 1.5 sleep 0.1 end def print_sine_curve(phase) s = (0..H).map { " " * W } (W - 1).downto(0) do |x| # x を逆順に回す y = Math.sin((phase+x)/W.to_f*2*Math::PI) s[((y + 1) * H / 2).round][x] = "¥e[41mo¥e[0m" end puts s.join("¥n") end
  24. Quine • 自分自身を出力するプログラム – Quine の名前の由来:間接自己言及を発見した 哲学者 Willard Van Orman

    Quine # Quine を実行して、出力を別ファイルに保存する $ ruby quine.rb > quine2.rb # 出力と元プログラムを比較する $ diff –s quine.rb quine2.rb ファイル quine.rb と quine2.rb は同一です
  25. うまくいく方針 • まとめると • 出力結果 – ほぼ一致、¥ がないだけ s="s=¥"...¥"; s=s.sub(¥"...¥");

    puts s"; s=s.sub("...", s); puts s s="s="..."; s=s.sub("..."); puts s"; s=s.sub("..."); puts s ※紙面の都合で改行を入れています
  26. ¥ の対処方法 • ¥ を使わずに書く – ¥ が必要な理由は、 "…" の中に

    " を入れるため – ならば、" を使わなければよい • %[…] という文字列リテラルを使う – ¥ なしで区切り文字自身を含められるのがポイント %[foo bar] #=> "foo bar" %[foo [bar] baz] #=> "foo [bar] baz"
  27. 動作する Quine • 書き直したプログラム • 出力結果 – 完全一致! s=%[s=%[…]; s=s.sub(%[…],

    s); puts s]; s=s.sub(%[…], s); puts s s=%[s=%[…]; s=s.sub(%[…], s); puts s]; s=s.sub(%[…], s); puts s
  28. 実習(15 分) • Quine を入力して実際に動かしてみましょう • もう少し短い Quine にしてみましょう –

    s=s.sub(%[…], s); puts s をまとめて puts s.sub(%[…], s) とするとか – 全部の "…" を %[…] に置き換えましたが、一部は "…" のままにできます • 発展:¥ から逃げずにQuineを書いてみましょう – ヒント:s の中の " をすべて ¥" に置換すればよい
  29. 解答 • 短くする – 文字列の中と外で 2 回変更することがポイント • 発展問題のヒント:???? を埋める

    – ¥ を置換するからと言って ¥ を使うとハマるので… s=%[s=%[…];puts s.sub("…",s)]; puts s.sub("…",s) s="s=¥"…¥"; puts s.sub(¥"…¥", s).gsub(????){????}"; puts s.sub("…", s).gsub(????){????}
  30. もっとかんたんな Quine • いちいち 2 箇所変えないと行けないのはダルい  eval を使えばもっとシンプルに書ける •

    動作の仕組みを実習時間に考えてみてください – ポイント:%[…] と %q[…] の違い eval(s=%q[puts %[eval(s=%q[#{ s }])]]) %[...#{ 42 }...] #=> "...42..." %q[...#{ 42 }...] #=> "...#{ 42 }..." ここで 1 時間 40 分くらい?
  31. その他のテクニック • 画像・動画生成 – 頑張ってデータを生成して出力する – 書籍の8.3節を参照のこと • サウンド –

    音声の波形データを生成して、どうにか再生する – 書籍の8.2節を参照のこと • プログラムの短縮 – 次ページ以降で解説
  32. コードゴルフ • プログラムの短さで競う競技 – "Anarchy golf" で検索 • 超絶技巧プログラミングは短さを競うわけではな いが、同じ挙動なら短いほうが大体エレガント

    – TRICK 等のサイズ制限を抜けるために必要なことも • 今回はRubyに特化した細かいテクニックではなく、 データの圧縮アルゴリズムを紹介します
  33. 超絶技巧プログラミングと圧縮 • 超絶技巧プログラムにデータを持たせたいケース – 形状データ、フォントデータ、楽譜データ、etc. • 基本的なアプローチ – 元データと圧縮コードを書いて圧縮データを作る –

    圧縮データと展開コードを最終的なプログラムに入れ る • 圧縮データは(通常は)文字列として埋め込む • 展開コードは Ruby で書いて埋め込む • 圧縮コードは最終的なプログラムに埋め込む必要がない
  34. トレードオフ • 単純な圧縮・展開アルゴリズム – 圧縮データは長い(低圧縮率) – 展開コードは短い • 頭のいい圧縮・展開アルゴリズム –

    圧縮データは短い(高圧縮率) – 展開コードは長い • なんとなくの目安 – データが30バイト程度なら無圧縮 – 100 バイト程度なら 36 進数 – 1000 バイト程度なら Byte-pair Encoding
  35. 36進数の例 • 元データ (横 3 × 縦 5 × 文字数

    11 = 165 バイト) • 空白を 0 、# を 1 にして二進数に • 10 進表示に (50 バイト) – 1073733623, 2905756245, 1063256021, 2371130133, 1063231487 • to_s(36)で36進数にすればさらに小さく(35バイト) – 0hr9u5z, 1c20fv9, 0hl19lh, 137pjpx, 0hl0qnz ### ## ### ### # # ### ### ### ### ### # # # # # # # # # # # # # # # # # ### ### ### ### ### # ### ### # # # # # # # # # # # # # ### ### ### ### # ### ### # ### ### 111 110 111 111 101 111 111 111 111 111 101 010 001 001 101 100 100 001 101 101 101 010 111 111 111 111 111 010 111 111 101 010 100 001 001 001 101 010 101 001 111 111 111 111 001 111 111 010 111 111
  36. BPE (Byte-pair Encoding) (1) • 繰り返しの多いデータで効く単純な圧縮 • 圧縮方法 – 元データのうち出現頻度の高い

    2 連続文字を見つける • "0000100000100001" の場合、"00" の出現頻度が最大 – その 2 連続文字を、未使用文字に置き換える • "0000100000100001"  "2212201221" – 利用した文字と 2 連続文字を先頭にくっつけておく • "2" + "00" + "2212201221"` – これを繰り返す • "2002212201221"  "3"+"22"+"2003130131"`
  37. BPE (Byte-pair Encoding) (2) • 展開方法 – 圧縮データ "3222003130131" –

    先頭文字と続く 2 文字を取り出す • "3" と "22" – "3" を "22" に置換する • "2003130131".gsub("3", "22") #=> "2002212201221"` – これを繰り返す • "2212201221".gsub("2", "00") #=> "0000100000100001"`
  38. Quine-relay の解説 • 理論的には、Ruby の Quine そのもの – 自分自身をそのまま出力するのではなく、 その文字列を出力する別言語プログラム、

    にラップして出力する – このラッピングを 100+ 言語分繰り返すだけ – 午後の実習ネタにあるので、考えてみてください
  39. Merry Quine-mas の解説 • 本質的には Ruby の Quine そのもの –

    自分自身をそのまま出力する前に、 アニメーションと音楽演奏を行う – アニメーションの方法はまさに講義で説明した通り – コードを 80x25 = 2000 文字に収めるのは 種々の圧縮テクニックが必要(収めなくてもよいけど)
  40. Monumental Quine の解説 – mquine.rb – 縁遠かった技術や、ふつうには出会わない制約を 体験できる 56 eval(_=%[b='DEILMQTVY';eval((%[a=(-1)EE0.5;f=->EfVf.each_slice(2)Y;c=->wVz=->dVd.mapVd=d.rotate(1)YY

    ;Q=->k,l,mV((m-k)E(l-k).conT).arQ<0Y;y=[];x=0.99;o,T=w.partitionV|n|d=0;z[n].mapV|k,l|y<<f[k,x,k,1,l ,1,l,x];d+=k.conTElY;d.arQ<0Y;f[o,T,[[0,d=2IEa,d+15,15]],o.map(Dd=:reverse),T.map(Dd),[]].mapV|o,T|T .mapV|h|z[h].max_byV|u,|u.realY;Y.sort_byV|i,|-i.realY.mapV|h|i,=h;v=0;o.mapV|n|z[n].mapV|x|m,l,E,k= x;e=(i-m).arQEE2;v<eDD(d=Q[k,m,l])^(Q[k,m,i]^d|(Q[m,l,i]^d))DDo.allMV|n|z[n].allMV|k,l|[i,m,k,l].uni q.size<4||Q[i,k,l]==Q[m,k,l]||Q[i,m,k]==Q[i,m,l]YYDD(v=e;w=n;T=Ex,m,Eh,i)YY;w[0..-1]=TY;o.mapV|v|t,= s=z[v];n=->rVk,m,l=r;k=k[2],l,m[2];r[I]=Q[Ek]DDv.allMV|q|z[k].anyMV|k,l|q==k||Q[k,q,l]YYY;z[s].mapV| k,l,m|l[0,2]=k,m;n[l]Y;(s[I..-1].mapVt=t[1]until(t[I]);k,m=l=t;m[0],k[1]=t;n[m];n[t=k];lY<<t).mapV|k ,m,l|y<<f[k[2],x,l,x,m[2],x]YY;x=1Y;yY;e=0;%[`^Tx52t<^cd,7/w(kabvbEz5arIwIa17.=c'slxr=-'4|e)EwkMI,_^ pvMVhsnME.rLw_k)^tp>+TIEduE45u>mv%^Y=Vny-`zce)k`heIt%`Vzf;c2nk4d|Vp^D_,,|kDDL2r_sDy%%fiMV6cYE)5`,m/k YQ/;IEezMVv,QchILY|p%%i<vstDt)=M7vLcT>=4Q2(vwael61//<ck>-l67uQ;2Tq,c_'qEIcm1cL;i++2-tYdbenq%pxr;2'Vn (uDa)n)zf4w)%5vh;ssV5kI;)z;2=+Toe<VL_D0`VLu;ook_y+eT`>IeT9-(i<MiVdd)ib_y+x`s^_u>M1s/mYQvEY`vMxu%Y0u5 7Qaoh2<Mkd'vtkp^zTc`E->Ep+icop_u0%=-zv,omq`Qz/41DV'`f9L5`M'bVxx%/;qLtq12%q:V'9,fD,ovu%qr|+e+rudI`Ir0 5chVd+Q5`II76rY0laT%b(I>Y%EQ1xf^|r,1)%4--zQa'<qxL-7Y0+|'vvbIxso0usv;%.I:pLQbe5a),Vu|91(0EIv^T>c5Dmd: 9-I15%Lp/>>z57^,Th2>%la0;5`dE1<xvrd09^9zz<.t,LpofrTTsQi'u5;Lwp7+zmm`'>qy;f6)||Ikw_0wdMM5<hmn64wbQ_rD m'>so7b..4qy`nQrz%Vf7Ii^epY(x=|49Lh(=>sI_sbofb7|qM,unaD%^i:|;_tEEnb-DDt`t%I2h;0x5f^yhs,pbLf+m^e>yqzQ '%::|^=,5-b=^_1x1se`kp,%wq4T%;'E.:Dsp_V-0||,)=;.a|<%0QY:;t:fEmk:4|_%o-.:aooq/6mThdvz4`uQqY1r'em.5'z1 2p7e%%pp6ebMM,m`5QpYx'd`,`6a4T)6Q.k.E.YsdiE^ox9pyrsr%|(kfn=y9q`6;=V<z%9(0cf^yp=:Irw-c/y>%iie%)y-1i(y 'V-n^uTva%l0Q>,yz;E0:LbV'eTb6MIb``Da.__ihbacxY|fc6>pTtl;ivVt,q>/%w,=hnI+i90>10u59te,Ildw4p94x`iwvs`f +^)w1M>%wf^].bytesV|i|e=eE59+(i-5)%L9Y;Q=->iVk=e%i;e/=i;kY;d=VI2=>c[[]]Y;54.upto(1I0)V|h|d[h%L9+I7]= c[(0..Q[5]).mapVl=o=T=[];n=0;(-2..Q[17]).mapV[l=Q[2],o=Q[1I]+Q[21]Ea+1+a]Y.flat_mapV|m,n|E,(h,)=[[o, l],[(o+o=n)/2,0]][0..lDl=m]Y.mapV|o,l|n=l<1M((n==0ML:1).upto(L)V|k|T<<h+kE(n-h)/4+kEkE(o-2En+h)/64Y; h=o;0):oY;TY]Y;n=[];m=0;v=aEE0.04;z=15/v.arQ;w=-0.2I;h='eval(_=%['+_+'])';h.tr(b,']+b+%[').bytesV|o| q=-w+s=wEm+=1;r=vEp=vEEmEz;d[o].mapV|v|n<<v.mapV|v,l|T,k=v.rect;[(p+(r-p)ET/=15)El,q+wET-k]YY;m<101D Dn+=[f[p,q,r,s,E[r,0]E(m/100),r,2,p,2],f[p,2,r,2,k=rET=0.976,2,TE=p,2],f[T,2,k,2,k,x=-715,T,x],f[T,x ,k,x,r,x,p,x],f[p,x,r,x,r,s-l=690,p,q-l,E[p,x+2]E(1/m)]];Y;T=VY;k=VY;l=''<<I2;m=n.mapV|i|(p,q),(r,s) ,(t,u)=Ei;p-=r;r-=t;Mf+l+i.mapV|m|[[T,:v,Em],[k,:vn,(rE(q-s)-pE(s-u))Ea,(p.conTEr).imaQ]].mapV|T,o,p ,w|T[[o,E(p.rect<<w).mapV|p|(pE500).round/z/10Y]El]||=T.size+1YE'//'YElY;o=''<<I5;puts(%(Q%squine')% l,o+%V'+(eval(%[Y+h+%V]);exit);'Y,T.keys,k.keys,m,o+M');]).tr(b,'%)27>fiz|'.tr('x%-|','%-'<<125)));' [[[ Monumental Quine (c) 2015 Yusuke Endoh -- tested with ruby 2.2.1 -- built on 2015/04/01 ]]]']) TrueTypeフォントデータの テキスト圧縮表現+レンダリング 穴ありポリゴンの凸多角形分割 3Dプリント可能なモデルデータ生成 コードを短くする (世俗的)インセンティブ 3Dプリンタ代:1行あたり約$15! 複雑な字形を使わない “3”, “8”, “g” などを一切不使用
  41. 放射線耐性 Quine の解説 • 文字列 x と y が一致したとき どちらも破壊されていない

     好きな方を eval すればよい • 文字列 x と y が異なるとき 長い方は破壊されていない  長い方を eval すればよい 57 x = ”…プログラム…” y = ”…プログラム…” eval x if x == y eval [x, y].max_by {|s| s.size } 次の疑問 : 文字列の外が破壊されたら? たとえば、ここのダブルクォートが消えたら?
  42. ネタ案 • 色のついたプログラム – $ cat prog.rb としたら、一部に色がついている – $

    ruby prog.rb としたら、何か動作する – ヒント1:puts "Hello" の H を赤くしてみるとか – ヒント2:プログラムを出力する プログラムを書くと簡単 • 色のついた Quine puts <<END puts "Hello" END
  43. ネタ案 • 自分自身を難読化して出力する Quine – 難読化は自由、簡単にはBASE64やROT13 • エンコードの方法 • コマンドラインでデコードする例

    • ruby prog.rb | base64 –d で自分自身が出たらOK require "base64" puts Base64.encode64("foo") #=> Zm9v $ echo Zm9v | base64 –d foo
  44. ネタ案 • 自分自身を出力する Pythonプログラムを出力する Ruby プログラム – ruby prog.rb |

    python で自分自身が出たらOK – (Python 以外の別言語でもご自由に) – ヒント1:Python の Hello, world • つまり、出力を print " と " で囲めばよい – ヒント2:エスケープ回避が必要 • ¥ を書きたくなったら 92.chr と書く • 興味があれば 3言語版、4言語版、…も print "Hello, world!"
  45. ネタ案 • もとに戻らず、変わり続ける Quine 風プログラム – ヒント:ベース形 • 実行するたびに n=1

    の部分が n=2 、n=3 、…と変わっ ていくようにする • 3 回実行して元に戻る Quine 風プログラム – n=1 の部分が n=2 、n=3 、n=1 、n=2 、n=3 、 …と変わっていくようにする • 実行のたびに色が変わる Quine 風プログラム – N の値を元に色つけを変える n=1;eval(s=%q[puts %[n=1;eval(s=%q[#{ s }])]])
  46. ネタ案 • 変な形状の Quine – こんなのとか  – アスキーアート化と うまく組み合わせると良い

    # ### ##### ####### ######### ########### ############# ############### ################# ###################
  47. ランダムアイデア • 行単位で sort しても動くプログラム – ruby prog.rb でも –

    sort prog.rb | ruby – でも動作する • 有名でないオプションを悪用したプログラム – ruby –x とか ruby –i とか • 発想法 – 「◦◦を Quine にするとどうなるか?」 – 過去の TRICK や IOCCC の入賞エントリを 眺めてみるとアイデアが浮かぶかも • http://magazine.rubyist.net/?0043-TRICK2013 • http://magazine.rubyist.net/?0053-TRICK2015 • http://ioccc.org/years.html – (遠藤が超絶技巧をはじめたきっかけも IOCCC の コードリーディングです)