縁あって、カロリーメイトリキッドのプロモーション用にちょっとしたRuby プログラムを書かせてもらいました。
↑のリンクを開いて、cd .Quine
したところにあるCML_quine.rb がそれです。cat CML_quine.rb
とすると中身が見えます。ruby CML_quine.rb
すると動きます。
実行してみましたか?サイト上で気楽に実行できるので、ぜひ試してみてください。
これがどういうプログラムなのか、簡単に解説しておきます*1 。
サイト上でruby CML_quine.rb
をするだけでも楽しめますが、自分のパソコンに保存するとより楽しめます。
まず、cat CML_quine.rb
した中身をまるごとコピーしてください。n=2;
で始まる行の頭から、'CalorieMate-Liquid-Quine'
で始まる行の終わりまでです。それをペーストして、CML_quine.rb というファイル名でローカルに保存してください。
そして、Ruby をインストールして、ターミナル(端末)でruby CML_quine.rb
で実行してください。Windows Terminal で動作確認しています。
Quine とは、実行すると自分のソースコードを出力するプログラムのことです。といっても、ソースコードをファイル読み込みして出力するわけではありません。ちょっとしたパズルのようなコードを書くことで、ファイル読み込みせずに自分を出力できます。詳しくはWIkipediaの記事や拙著『あなたの知らない超絶技巧プログラミングの世界』をご覧ください。
そして、このプログラムはQuineみたいなもので、実行するとまずソースコードを出力し、それからアニメーションをします。
「みたいなもの」と言ったのは、1回実行しただけではちょっとだけ違う結果になるからです。サイトのreadme.mdにも書いてありますが、次のように3回実行を繰り返すと元に戻るようになっています。
$ ruby CML_quine.rb > CML_quine2.rb$ ruby CML_quine2.rb > CML_quine3.rb$ ruby CML_quine3.rb > CML_quine4.rb$ diff -s CML_quine.rb CML_quine4.rbファイル CML_quine.rb と CML_quine4.rb は同一です
各プログラムの違いは、『フレーバー』です。CML_quine.rb とCML_quine2.rb とCML_quine3.rb をそれぞれ単体で実行すると、いずれも同じアニメーションをしますが、最終的に出来上がるフレーバーが変わるようになってます。次のように実行してみてください。
$ ruby CML_quine.rb$ ruby CML_quine2.rb$ ruby CML_quine3.rb
このアニメーションは、エスケープシーケンスを使って色付き文字のモードにしたり、カーソルを移動したりすることで行っています。
ロゴを描くためのカーソルの動きのデータは、すべてコード中に埋め込まれています。そのままだと巨大になってしまうので、バイトペア符号化によって圧縮しています。
最後。缶に黄色い液体が注ぎ込まれるアニメーションですが、これは決まった動きをハードコーディングしているわけではなく、流体シミュレーションを使って実行時に計算しています。流体力学の原理であるナビエ-ストークス方程式をSmoothed Particle Hydrodynamicsと言われる方法で数値的・近似的に解きます。簡単に言えば、液体を表現する粒子同士がお互いに押し合ったり(圧力)、粘ついたり(粘性)、重力に引っ張られたり(外力)するのをシミュレーションしています。
実はここは、以前C言語で書いたコードの移植です*2 。こちら。
ただ、今回はシミュレーションの精度を上げるために粒子の数を増やしたこともあって実行速度が遅くなってしまったので、空間分割法を実装して高速化しました。
「プログラムを表示した後、アニメーションで上書きしちゃったら Quine にならないじゃないじゃん!」と思う人がいるかもしれません。しかし、背景色と文字色が同じになってて読めないだけで、実は文字はちゃんと表示されています。次の動画のように端末からコピペすれば実行できます。
カロリーメイトリキッドのプロモーション用に、Ruby でちょっとした面白プログラムを書かせていただきました!
— Yusuke Endoh (@mametter)2020年8月5日
次のサイトを開いて、cd .Quine と入力し、さらにrubyCML_quine.rb を打ち込めば動きます。Quine の前のピリオドを忘れないこと。https://t.co/Mh5xgpaFU0pic.twitter.com/RZcpP2qcsI
「出力にエスケープシーケンスを混ぜたらプログラムとして実行できない!」と思う人がいるかもしれません。しかし、エスケープシーケンスはコメント内に出すようになっているので、実はちゃんと動きます。次のように実行すれば、エスケープシーケンス入りのCML_quine2.rb がちゃんとプログラムとして動くことがわかります。
$ script -q -c "ruby CML_quine.rb" /dev/null | tee CML_quine2.rb$ ruby CML_quine2.rb$ vim CML_quine2.rb
このコードはカロリーメイトリキッドを 3 種類ぜんぶ飲みながら実装しました。
以上の処理はどこか見えないところに隠されているわけではなく、cat CML_quine.rb
で見ることができる 22 行のプログラムの中にすべて詰め込まれています。プログラミング言語Ruby の簡潔さ・強力な言語機能・柔軟性を悪用するとこんなこともできるんですよ。他の言語ではなかなかむずかしい。
ということで、腕に覚えのある人はぜひ解読してみてください!他にもここで解説しなかった工夫がいくつか仕込まれています*3 。
なお、Quine に興味がある人は、拙著『あなたの知らない超絶技巧プログラミングの世界』に詳しいやり方からたくさんの実例までむちゃくちゃ詳しく書いてあるので、ぜひ読んでみてください。(宣伝)
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。