部内の発表資料 自作のEsolang「emojifunge」でQuineに挑戦したので発表。 解説付き。
自作のesolangでQuineに挑戦してみた5/30 @ten986
View Slide
前提知識: esolangとは● esolang: 難解プログラミング言語● 基本的に、実用性を目指さないジョーク言語● 見た目にユニークなもの、難しさを極めたもの、ゴルフに特化したもの、などさまざま● 例: Brainfuck による Hello, world!
前提知識: Quineとは● Quine: ソースコードと出力が一致するコード● Ruby による Quine が有名● これはソースコードと出力が一致する○ eval s="puts'eval s='+s.inspect"
背景: paiza_run が壊れた話● https://togetter.com/li/1098185● #paiza_run ruby:[rubyのコード] というツイートをすると、@paiza_run が出力をツイートする● [rubyのコード]が、#paiza_run ruby:[rubyのコード] を出力するコードである場合、無限ループする● という事件を最近知った
背景: 例会講座通知が届く● そんな中、例会講座botから指名を受ける● ひとまず締切を決めたら動くだろうから、5/30に入れる● ネタはどうしたもんか・・・● → esolang で Quine をやればよいのでは!!??
背景: esolang の Quine について● 調査してみる● KMCの人は強いから聞いたら情報くれるやろ(丸投げ)● mametter 氏によるスライドを教えてもらう● やべ〜w
背景: なら自作のesolangで● esolang による Quine には前例があった● そういえば以前にesolangを作ったことがあった● 自作esolangでQuineに挑戦してみよう!!!● そして今に至る......
自作esolang「emojifunge」● emojiを二次元に配置し、ポインタがその上を動くスタック指向言語● スタックのネストなど、スタック機能が強力● 命令セットがユニーク● emojiの出力機能も備える● https://github.com/ten986/emojifunge-lang
emojifungeでQuineを作ろう!● 早速ですが、emojifungeでQuineが組めました!● 次のスライドにコードを載せました!● コードの全貌を見てみましょう!
📜
📜・・・🤔
emojifungeにはQuine命令があった● emojifunge には Quine をする命令があった● これ1文字書けば、なんとプログラムと出力が一致する!!!!!!● たった 4byte で Quine が実現!!!!!!
余談: HQ9+● HQ9+ という言語がある● 4命令しかなく、「Q」でQuine が実現する● もちろんチューリング完全ではない
そういうことではない● Quine は実現したが、求めているものではない● 華麗な、奇妙な実装からくるプログラムの奥深さがQuine に求めているもののはず● こんなものでいいのか?
ちゃんと Quine を実装しよう● 📜のようなズルはせずに Quine を実装する● mametter 氏によるスライド のほか、angel_p_57氏のWhitespaceのQuineの記事 が実装の上で参考になりそう(なった)
ちゃんと実装したものがここに● ちゃんとemojifungeでQuineを実装しました● このために今日朝5時まで作業してた(は?)● 次のスライドに載せる他、gist にも上げました● https://gist.github.com/ten986/fbd05be46d9c750b0909af3be6776550
おめでとうございます● emojifunge で Quine が実現できました○ やったね!● ちゃんと出力も一致している● ちなみに、1行目は約30,000文字あるっぽい(?)
解説をしていく● 実装できたので、実装解説をします● angel_p_57氏のWhitespaceのQuineの記事を参考に、「A, B, C」という各部に分けて解説
ABCAをコピーAの左を出力Aの右を出力
概要● emojifungeは、codeUnit によるスタックを emoji として扱う○ codeUnit: https://jsprimer.net/basic/string-unicode/○ 0⃣ の codeUnit は [48, 65039, 8419] である○ emojifunge はスタックのネストができる○ [ [48, 65039, 8419], [48, 65039, 8419], [48, 65039, 8419] ] というスタックにより、0⃣0⃣0⃣が表せるはず● emojifunge のコードは、emoji + 改行 で表される○ 改行は、長さ0のスタック [] で表すことにする● つまり、スタック列でemojifungeのコードを表すことができる
概要● 処理順としてはこう● A:2行目以降のコードを表すスタック列を載せる● (このスタック列全体を1つのスタックにまとめ、複製する)● B:スタック列に対し、「そのスタック列を載せるようなemojifungeのコード」を出力○ つまり、Aの部分が出力される● C:スタック列に対し、「そのスタック列の表すemoji列」を出力○ つまり、2行目以降が出力される
AとBの対応の補足● Aの先頭は「2行目以降のコードの先頭にある⬇のcodeUnit [11015,65039] を載せるコード」● 「11015という数に対して、先頭に 0⃣ を置き、「各桁 ➕」と間に「🔟 ✖」、65039についても同様、長さ2のcodeUnitなので2⃣、最後に 💌 を置く」と機械的な操作● この「機械的な操作を表すemoji列」をBでは出力する
Bを組む● Aは、2行目以降の内容が確定した後、機械的に生成するとよい● すなわち、B以降を組むことになる
Bを組む: 概要● スタック列がある。codeUnitのスタックか空スタックの列● スタック列の長さが0なら終了する● スタック列のトップが空スタックなら○ 空スタックを載せるコードである「📧」を出力● スタック列のトップがcodeUnitのスタックならその中に入る○ codeUnitのスタックの長さが0ならスタックを抜ける○ 数を10進数の各桁に分解する○ 先の「機械的な操作」に当てはめてemojiを出力する○ スタックを抜ける時、「機械的な操作」の長さ部分を出力
Bを組む● スタック列の長さが0なら終了する
Bを組む● スタック列のトップが空スタックなら○ 空スタックを載せるコードである「📧」を出力● 📧 のcodeUnitを載せて出力するだけ● 「機械的な操作」にならっているが、ならう必要はない
Bを組む● スタック列のトップがcodeUnitのスタック● 数を10進数の各桁に分解する● うまいことループさせます
Bを組む● 先の「機械的な操作」に当てはめてemojiを出力する● 11015という数に対して、先頭に 0⃣ を置き、「各桁 ➕」と間に「🔟 ✖」● このそれぞれをcodeUnitに変換してスタック列を積む● 1つのcodeUnitを作るのも大変なんです
Bを組む● スタックを抜ける時、「機械的な操作」の長さ部分を出力● 長さ2のcodeUnitなので2⃣、最後に 💌 を置く● 長さは事前に 📥 という命令で退避させてある
Cを組む● Bがあんなのでしたが、Cは簡単です● codeUnitのスタックか空スタックの列かで分岐○ 空スタックなら、改行を出力 🔟🔡○ codeUnitのスタックなら、emojiと見なして出力🔣● 簡単!!!!!!
Aを組む● A以外の部分が組めたら、Aを書く● 2行目以降を入力に、「機械的な操作」を出力するコードを別途書く● 30,000文字くらい出力される、手作業は厳禁
完成!● というわけで Quine が完成しました● 大変でしたね
今後の展望● やはりWebインタプリタが欲しい○ Quine をせっかく作ったが、手軽に実行できない● emojifungeの謎命令でシュッとした Quine が書きたい○ あまりモチベはないが、ヤバいことはできそう