Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Yusuke Endoh
March 18, 2022
Programming
110
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
https://cookpad.connpass.com/event/238257/
Yusuke Endoh
March 18, 2022
More Decks by Yusuke Endoh
See All by Yusuke Endoh
Practical TypeProf: Lessons from Analyzing Optcarrot
mame
1
3.4k
型システムを知りたい人のための型検査器作成入門
mame
15
5.5k
TRICK 2025 Results
mame
0
6k
Writing Ruby Scripts with TypeProf
mame
1
1.6k
An Invitation to TRICK: How to write weird Ruby programs
mame
1
1.5k
TypeProf進捗
mame
0
140
12年前の『型システム入門』翻訳の思い出話
mame
14
2.9k
Good first issues of TypeProf
mame
4
11k
Revisiting TypeProf - IDE support as a primary feature
mame
1
4k
Other Decks in Programming
See All in Programming
ハーネス設計入門 〜 基礎知識の整理から実務へのステップアップ 〜
kinopeee
28
33k
残高管理から台帳サービスへの進化
artoy
1
200
dotNET_vulnclicker_intro.pdf
deka_morita
0
140
Kotlinの15年とServer-Side Kotlin
n_takehata
1
150
Jetpack Compose Mechanisms
skydoves
3
820
Vue Fes Japan の “作る側”に関わってみて
naokihaba
0
160
ChromeでローカルLLM
ryu1013
0
140
Unity6 URPによる海底をテーマにしたVJシステムの解説 | Unity Shader 完全に理解した 勉強会
gam0022
0
370
月間100万人のサービス刷新で、 技術選定をHonoに振り切った話
yutobara
8
6.7k
ActionController meets Protocol Buffers
sorah
0
560
sbt 2.0: takeoff
eed3si9n
0
160
パスワード再設定メールのURLについて知っておこう
uyuki234
0
160
Featured
See All Featured
Joys of Absence: A Defence of Solitary Play
codingconduct
1
550
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
450
Self-Hosted WebAssembly Runtime for Runtime-Neutral Checkpoint/Restore in Edge–Cloud Continuum
chikuwait
0
890
The agentic SEO stack - context over prompts
schlessera
0
970
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.6k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
850
My Coaching Mixtape
mlcsv
0
360
Visualization
eitanlees
153
17k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
310
世界の人気アプリ100個を分析して見えたペイウォール設計の心得
akihiro_kokubo
PRO
74
43k
Paper Plane
katiecoart
PRO
5
54k
Mobile First: as difficult as doing things right
swwweet
225
10k
Transcript
クックパッド 春の超絶技巧パンまつり 超絶技巧プログラミング編 講師:遠藤 侑介(@mametter) 1
講師:遠藤 侑介(@mametter) •プログラミング言語Rubyの開発が仕事です • ちょっと変なプログラムを書きます 2
TA:茂呂 智大 (@slightair) • エンジニア統括マネージャー 兼 モバイル基盤部 部長 • エンジニア組織づくり、採用、社内のモバイルアプリ
開発基盤の環境改善が仕事です • Ruby の開発はしていませんが Ruby はよく書きます、 大好きです • 変なプログラムは書けませんが、それがどうして動く のか考えるのは好きです 3
4
5 eval$s=%q(;eval" "+%w(z=?¥s;t=z+?¥n;$><<( t*5+"eval$s=%q(#{$s.gsub(/#.*/){ $&.tr(z,?¥x21)}})¥n"+t+(0..6).map{|y |(0..47).map{"co@@@@@@okpad¥x21".upcas e["h7sam@@@@@@b@@ @@jw@@@@@@@24yz3n dq4vk3q@@ @
@@ @@tzcro eg26ut5@ @ @2xbkt rzzvizj@ @j1uy1 ubzk8xhw@ @ @fj3q33 0".to_i(3@@ @@@@@@6)[_1*7 +y]>0?_1/7:@@@ @7]}<<?¥n}*""+ t*5).gsub(/.@ @+/){$&.strip .center(66)@ @@@@@@@@@@@@@@@}.gsub(/./){t =?¥x21==$&@ @;u=$`.size>1 800;"¥e[@ @48;2;#{u&&t| |z==$&?"@@@@@@@@@@@@@@@@@@255;255;255" :u||$&==?¥x40?"64;28;0":"255;153;51" }m#{(t)?z:$&}¥e[0m"};exit).join. ## (C) 2022 Cookpad Inc. gsub(?¥x40,"")) https://gist.github.com/mame/97d352962539d5065e97487d287e74aa
6
クックパッドロゴのQuine •Quine:ソースコード自身を 出力するプログラム ※特別な許可をもらって作ってます! 会社のロゴは大切な知的財産なので、 他者のロゴを勝手にQuineにするのはやめましょう 7 eval$s=%q(;eval" "+%w(z=?¥s;t=z+?¥n;$><<( t*5+"eval$s=%q(#{$s.gsub(/#.*/){
$&.tr(z,?¥x21)}})¥n"+t+(0..6).map{|y |(0..47).map{"co@@@@@@okpad¥x21".upcas e["h7sam@@@@@@b@@ @@jw@@@@@@@24yz3n dq4vk3q@@ @ @@ @@tzcro eg26ut5@ @ @2xbkt rzzvizj@ @j1uy1 ubzk8xhw@ @ @fj3q33 0".to_i(3@@ @@@@@@6)[_1*7 +y]>0?_1/7:@@@ @7]}<<?¥n}*""+ t*5).gsub(/.@ @+/){$&.strip .center(66)@ @@@@@@@@@@@@@@@}.gsub(/./){t =?¥x21==$&@ @;u=$`.size>1 800;"¥e[@ @48;2;#{u&&t| |z==$&?"@@@@@@@@@@@@@@@@@@255;255;255" :u||$&==?¥x40?"64;28;0":"255;153;51" }m#{(t)?z:$&}¥e[0m"};exit).join. ## (C) 2022 Cookpad Inc. gsub(?¥x40,""))
今日のテーマ:超絶技巧プログラミング •あえて実用性のないプログラムを書いて遊ぼう • ふつうのRubyコードの話はしません • クックパッドの業務の話もしません 8
超絶技巧プログラミングで得られるもの •コンピュータ科学の理論にふれるきっかけ •プログラミング言語についての深い理解 9
今日の流れ •13:15~14:15:講義 •14:15~17:00:実習 • 17:00~18:00:発表会 •超絶技巧プログラミングコンテストに投稿を! • TRICK 2022(締切:2022/07/31) •
https://github.com/tric/trick2022 10
講義内容 •➔超絶技巧プログラミングの事例紹介 • 基本テクニック3点 • プログラムをアスキーアートにする • ターミナルで遊ぶ • Quineを書く
11
Quineリレー • 自分自身を出力する REXXプログラム、を出力する rcプログラム、を出力する … Scalaプログラム、を出力する Rustプログラム、を出力する Rubyプログラム https://github.com/mame/quine-relay/blob/master/QR.rb
12
Green-square Quine • https://github.com/mame?from=1970-01-01&to=1970-12-31 eval s=%q"n=t • https://github.com/mame/green-square-quine 13
もっと見たい人は •参考書をみてください 14
講義内容 •超絶技巧プログラミングの事例紹介 •➔基本テクニック3点 • プログラムをアスキーアートにする • ターミナルで遊ぶ • Quineを書く 15
Tip 1: アスキーアートプログラム 1. 好きなRubyプログラムを書く 2. 空白と改行と円マーク ¥ を避ける 3.
おまじないで囲む 16 puts "Hello world!" puts("Hello"+32.chr+"world!") eval(%w( puts("Hello"+32.chr+"world!") )*"") この範囲を自由に整形できる
たとえば 17 eval(%w(put s("Hello"+3 2.chr+"worl d!"))*"") eval(%w(puts( "H el lo
"+ 32 .c hr +" world!"))*"") eval(%w(p ut s( "H el lo "+ 32 .c hr +" wo rl d!"))*"") つぶしたり 四角にしたり 円にしたり メソッド名や数字の途中で 改行してもOK 文字列の途中に スペースいれてもOK
仕組み •Rubyの%w記法は「文字列の配列」を返す • 配列を掛け算すると連結した文字列になる • evalは文字列をコードとして実行する 18 %w(pu ts( 42))
#=> ["pu", "ts(", "42)"] %w(pu ts( 42))*"" #=> "puts(42)" eval(%w(pu ts( 42))*"") #=> 42
練習問題(5分) • 自己紹介を出力するプログラムを イニシャル形状にしてみましょう • 余分はコメント(#)などで埋める • 別のメッセージ・形状でも可 •gistに置いてSlackへ提出ください 19
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)
解説 •正解はありません、動けばOK! •手編集が面倒くさいなあと思ったら→自動化 20 code = %q(puts("YusuKe-Endoh,hobby:walking")).chars puts <<END.gsub("#") {
code.shift || "#" } ## ## ###### ## ## ## #### ###### ## ## ## ## ###### ## END
Tip 2: ターミナルで色の表示 • "¥e[数字m"で色を指定、"¥e[m" で指定解除する • 最近は"¥e[38;2;R;G;Bm"でRGB指定もできる • 注:cmd.exeやTerminal.appでは動かない
• Windows TerminalやiTerm2を使ってください 21 puts "¥e[31mfoo¥e[m" #=> foo(赤い字になる) puts "¥e[41mfoo¥e[m" #=> foo(背景が赤くなる) puts "¥e[38;2;255;0;0mfoo¥e[m" #=> foo puts "¥e[48;2;255;0;0mfoo¥e[m" #=> foo 30黒 40黒 31赤 41赤 32緑 42緑 33黄 43黄 34青 44青 35紫 45紫 36水 46水 37白 47白
練習問題(5分) •好きな色付きメッセージを出してみましょう •発展:コードをアスキーアート化しましょう • おまじない eval(%w( ... )*"") で囲む •
ヒント:"¥e[数字m" のかわりに 27.chr+"[数字m" 22 $ ruby color-message.rb Hello, world!
解説 •たとえば • アスキーアート化するには 23 puts "¥e[37;46mHello¥e[m ¥e[33;41mworld!¥e[m" eval(%w( e
= 27.chr; puts(e+"[37;46mHello"+e+"[m"+32.chr+e+"[33;41mworld!"+e+"[m") )*"")
なぜ円マークは使えない? •¥ と e の間に空白や改行が入ると動かなくなる • 興味があったら実習時に試してみてください 24 eval(%w( puts("¥
e[37;46mHello¥e[m") )*"") ここに空白が入ると意味が変わる
Tip 3: Quine •自分自身を出力するプログラム • 哲学者Willard van Orman Quineに由来 25
$ ruby quine.rb > quine2.rb $ diff –s quine.rb quine2.rb ファイル quine.rb と quine2.rb は同一です
間違ったQuineの書き方 • …を出力するプログラム • それを出力するプログラム • それを出力するプログラム • この方針は明らかにきりがない 26
puts "..." puts "puts ¥"...¥"" puts "puts ¥"puts ¥¥¥"...¥¥¥"¥""
ただしいQuineの書き方(1) •…を出力するプログラム • このコードを eval で包む • %q[...] は文字列リテラル "..."
とほぼ同じ 27 puts "..." s = %q[puts "..."]; eval s
ただしいQuineの書き方(2) • … の代わりになるべく↑を出力するようにする 28 s = %q[puts "s =
%q[...]; eval s"]; eval s s = %q[puts "..."]; eval s
ただしいQuineの書き方(3) •… の位置に入るべき文字列は、変数 s そのもの •答え: 29 s = %q[puts
"s = %q[" + s + "]; eval s"]; eval s #=> s = %q[puts "s = %q[" + s + "]; eval s"]; eval s s = %q[puts "s = %q[...]; eval s"]; eval s
練習問題(10分) • Quineを実際に動かしてみましょう • ちょっと違う形式でQuineを書いてみましょう • 【やや難】自分自身を反転して出力してみましょう • 【難】自分自身を赤字で出力するようにしましょう •
ヒント:%q[...] は %q{...} などに置き換えよう 30 eval(s = %q[puts "...ここを埋める..."]) s = %q[puts "s = %q["+s+"]; eval s"]; eval s
解説 •答え: • 文字列内の式展開を使ってもいいです •赤字Quine: 31 eval(s = %q[puts "eval(s
= %q[" + s + "])"]) eval(s = %q[puts "eval(s = %q[#{ s }])"]) eval(s = %q{puts 27.chr+"[31meval(s = %q{"+s+"})"+27.chr+"[m"})
講義はここまで 32
実習 • 好きなプログラムを自由に書いてください • 講義内容を参考にしても、しなくてもよいです • 次ページのネタ案も参考に • 15:30ごろから講師とzoom雑談(1人3分くらい) •
何を作ろうとしてるか講師に聞かせてください! • 17時ごろから発表 • githubに置いてSlack提出してください(gistでも可) 33
ネタ案:へんな見た目のプログラム •アスキーアートの形をしたQuine • アスキーアート+色+Quine • 今回の講義内容の組み合わせでできる(はず) • ヒント:Quineの中にアスキーアート化のおまじないをうまく混ぜる • 【難】色がついたまま
実行可能なQuine • ヒント:コード中にエスケープ シーケンスを混ぜる 34 $ ruby quine.rb eval(...色つきコード...) $ ruby quine.rb | ruby eval(...色つきコード...)
ネタ案:エンコードQuineを極める • 自分自身を難読化して出力するQuine • ヒント:putsの前にBase64.encode64を通せばよい • 【やや難】自分自身を出力するPythonプログラムを 出力するRubyプログラム • ヒント:Pythonの"""文字列リテラルを使うとちょっと簡単かも
35 $ ruby base64-quine.rb | base64 –d > base64-quine2.rb $ ruby base64-quine.rb | python3 > base64-quine2.rb
ネタ案:Quineを進化させる •実行のたびに長くなるQuine風コード • ヒント:普通のQuineにコメント # を足すだけでできます •【難】実行のたびに1増えるQuine風コード 36 eval(s=%q[...ここを埋める...]) #=>
eval(s=%q[...ここを埋める....])# #=> eval(s=%q[...ここを埋める.....])## n=1;eval(s=%q[...ここを埋める...]) #=> n=2;eval(s=%q[...ここを埋める...]) #=> n=3;eval(s=%q[...ここを埋める...])
ネタ案:アスキーアートを極める •【やや難】コードより大きいアスキーアートを 表示する • 300文字のコードで横40 x 縦20(800文字)の アスキーアートを表示するなど • 圧縮を実装する必要がある
• ランレングス圧縮、Byte Pair Encodingあたりが簡単 • 基本的な構造→ 37 data = "アスキーアートを圧縮したデータ" print(展開(data))
ネタ案:形状を変化させるQuine •【激難】"A"形状と"B"形状を行き来するQuine • 初期状態は"A"形状 • 実行すると自分自身を"B"の形にして出力する • "B"の形を実行すると"A"に戻る • ヒント:アスキーアート化プログラム+圧縮+Quine
全部組み合わせる必要がある 38
ネタ案:アニメーション •端末に何回も上書きする •エスケープシーケンスを使う • ¥e[H • カーソルを画面左上に移動する • ¥e[2J •
画面の内容を全部消す • 参考:https://en.wikipedia.org/wiki/ANSI_escape_code 39 print "¥e[H¥e[2J" (0..).each do |i| print "." * (i%10) print ":" print "." * (9-i%10) print "¥e[H" sleep 0.1 end
ネタ案:その他 • 【難?】今日の内容をRuby以外の言語で再現する • evalや%w()がとても便利なことがわかる • 【?】自分の得意な技術と今日の内容を組み合わせる • アスキーアート ×
競技プログラミングのアルゴリズム • Quine × Next.js、Quine × Unity、Quine × AI • うまくできたら → https://github.com/tric/trick2022 40
余談:哲学者QuineとプログラムQuine(1) •命題: • この命題は真とも偽とも言えない •「この命題」で命題自身を参照してるのが肝 • 次のQuineと同じ構造 41 この命題は偽である puts
File.read(__FILE__)
余談:哲学者QuineとプログラムQuine(2) •哲学者Quineが研究した間接的自己言及の命題 • 「この命題」みたいなインチキなしで 同じ構造を作り出している • expr => v は
v = expr と(ほぼ)同じ意味 • s.dumpは文字列を引用形式にする 42 「は、自身の引用を前置されると偽になる」は、 自身の引用を前置されると偽になる " => s; puts s.dump + s" => s; puts s.dump + s
余談:哲学者QuineとプログラムQuine(3) • 自己言及は計算機の理論分野でわりと登場する • 停止性問題 • プログラムが有限時間で停止するかどうかを判定するアルゴ リズムは書けない • クリーネの再帰定理
• チューリング完全な言語では自己言及が構成できる • ゲーデルの不完全性定理 • よくわかりません • 興味があったら→理論計算機科学、数理論理学 43
おわり •超絶技巧プログラミングとは、 おもしろい理論・技術をおもしろく実践する遊び •作ったものはぜひ発信していきましょう • 感想記事でも、YouTubeでも、GitHubの肥やしでも • うまくできたら → https://github.com/tric/trick2022
44