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.3k
型システムを知りたい人のための型検査器作成入門
mame
15
5.4k
TRICK 2025 Results
mame
0
5.8k
Writing Ruby Scripts with TypeProf
mame
1
1.6k
An Invitation to TRICK: How to write weird Ruby programs
mame
1
1.4k
TypeProf進捗
mame
0
130
12年前の『型システム入門』翻訳の思い出話
mame
14
2.9k
Good first issues of TypeProf
mame
4
10k
Revisiting TypeProf - IDE support as a primary feature
mame
1
3.9k
Other Decks in Programming
See All in Programming
市販E-Readerを乗っ取れ 〜Embedded Swiftで電子ペーパーガジェットを制御する〜
trickart
0
190
XP祭りでしか伝わらないフリップネタ #xpjug
murabayashi
0
150
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
2.8k
AI が書く Go コードの品質を劇的に向上させる Linter: “declscope”
mpyw
0
330
cdk deploy JawsSonic #MARATHONしながらAWSリソースをデプロイしてみよう
akihisaikeda
2
130
Streamlitで実現する自然言語データアプリ開発
ayumu_yamaguchi
0
280
AIを上手に使っていこうとしたら越境せざるを得なくなった話 〜実践1年で見えた境界を越えなければならない理由と進め方〜 / Crossing borders with AI
tomoyakitaura
4
1.2k
一参加者から『中の人』へ 〜全通PHPerがブースに立って学んだ、カンファレンスを100倍楽しむコツ〜
wp_daisuke
0
150
ゲームコントローラやキーボードのファームウェアをSwiftで書く
kishikawakatsumi
1
240
GraphRAGのKnowledge Graphを 直接!見る/View-GraphRAG's-KnowledgeGraph-directly!
tyumugi1113
1
320
大喜利で理解するLLM as a Judge / Understanding LLM-as-a-Judge through Ogiri
rockname
0
110
スマートフォンでモールス信号を送受信する 〜スマートフォンのLEDとカメラで作る光通信の設計と実装〜
atsuki_seo
0
120
Featured
See All Featured
JAMstack: Web Apps at Ludicrous Speed - All Things Open 2022
reverentgeek
1
600
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.6k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Building a Scalable Design System with Sketch
lauravandoore
464
34k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Why Our Code Smells
bkeepers
PRO
340
58k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
840
Fireside Chat
paigeccino
43
4k
The Cost Of JavaScript in 2023
addyosmani
55
10k
For a Future-Friendly Web
brad_frost
183
10k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.9k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
580
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