「○○○は、Hello Worldを表示するプログラムだったんだよ!!」
「Ω ΩΩ<な、なんだってー!?」
本来プログラム言語といえばはじめに文法が決まっていて、そこに文法に従った文字列を入れると実行可能な何かができあがるというのが普通の流れです。
これを逆にしたらどうなるかと思ったのが今回の話題です。つまり、欲しい出力結果があって、適当な文字列があったとき、それをプログラム言語にするようなインタプリタを出力するプログラムを作ろう、というものです。メタプログラミングという用語をはじめて聞いたときに浮かんだ個人的イメージだったり。
もう少し動機を素直に言うと、Brainfu*kの仲間を見てふと思ったのです。Brainfu*k風のプログラム言語ってたくさんあるのですが、どれも本来の雰囲気を損なわないような入力文字列の例(だいたいHello World)を頑張って作っているじゃないですか。
名状しがたいプログラミング言語のようなもの
ジョジョ
長門有希
てってってー
プログラミング言語KQ
(ん、直書きで本来の雰囲気になっている場合も多い?)
でも、そこそこ長い文字列さえあれば、適当に文法を用意して勝手にプログラム言語にできるんじゃないかなと。
今回も目指す出力はHello World。Wikipediaを見ると、Brainfu*kでHello Worldを書くプログラムは例えば以下のように書けるようです。
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>—.+++++++..+++.>>.<-.<.+++.——.——–.>>+.>++.
106文字。思いつく最も簡単な方法としては、文章のうち1度しか出現しない単語を集め、順にこの文字に対応させていけば良いわけです。単語を取り出す部分が厄介ですが…今回は形態素解析を使います。英語だと分割も簡単なのですが、今回はプログラム言語でない日本語を扱うわけだし、仕方ないよね。
というわけで、「文章を入れるとその文章に対してはHello Worldを出力するBrainfu*kインタプリタを返すプログラム」というのができました。Brainfu*kの8命令の中で値を代入のみ定義されませんが、まあ適当な単語を割り当てておけばいいので今回はスルーします。プログラム本体は…公開しなくていいですよね?
(追記: スクリプトのソースを置いておきます。Python実行環境およびMeCabが必要です。ライセンスは改変元のものを尊重してWTFPLとします。)
さっそく長文を入れて実験。簡単に手に入る整った長文といえば…やはり日本国憲法。日本国憲法をプログラム言語にしてもらいましょう。
以下がプログラム言語「日本国憲法」の文法一覧です。
値をインクリメント:「全権, 宣言, 文書, 確定, 発動, 人間, 威嚇, 不断, 排除, 専念, 協和, 念, 接受, 享受, 子孫, 自覚, 信義, 永遠, 昭和, 個人, 賜, 書, 全土, 由来, 惨禍, 権威, 十一月, 希求, ここ, 濫, 任免, 世界, 日本国憲法, 賠償, 恵沢, 平穏, 法令, わが国, 公共団体, 批准」
値をデクリメント:「普通選挙, 最大, 戦力, 皇位, 責, 勲章, 貴族, 一代, 経済, 継承, 追求, 欠, 伴, 圧迫, 固有, 全体, 公, 制度, 成年, 世襲, 華族」
ポインタをインクリメント:「厳粛, 誓, 恒久, 政府, 解決, 総意, 救済, 福利, 確認, 手, 免, 公正, 恐怖, 廃止, 不法行為, 除去, 地上, 達成」
ポインタをデクリメント:「専制, 道徳, 要件, 安全, 隷, 軍, 信頼, 各国」
括弧:ポインタの指す値が0なら対応する閉じ括弧へジャンプ:「確保, そもそも, 無視」
閉じ括弧:ポインタの指す値が0でなければ対応する括弧へジャンプ:「全力, 偏狭, 対等」
なんとまあ…お固いプログラム言語が出来上がりました。権威が値をインクリメントで普通選挙が値をデクリメントだったり、恐怖がポインタのインクリメントで信頼がポインタのデクリメントだったり、なんとなく気になる部分もありますが、とにかくプログラム言語です。これらの文字列を使って任意のプログラムを記述できます。日本国憲法を書けばHello Worldになります。
ボキャブラリー的に校長先生のお話くらいなら何らかのプログラムになるかもしれません。停止するかどうかはわかりませんが…
(追記: プログラム言語「日本国憲法」のインタプリタのソースを置いておきます。)
いや、私は別に日本国憲法をプログラム言語にしようとしていたわけではないのです。プログラム言語にしたかったのはどちらかというとアレです。最も有名なコピペとも言われるアレ。語彙が妙に少なく、はじめからプログラム言語だったんじゃないかとすら思えるアレです。
アレ、残念なことにユニークな単語が少なすぎて、今のままでは同じ手法でHello Worldが作れないのです。
仕方がないので対応させる命令を減らす工夫をします。しかし始めからメモリにHello Worldを読み込んでおくHQ9+みたいなことをすれば解決は可能で、それはおもしろくないのでもう少し一般的なやり方にしたいところです。といっても複数回登場する単語を命令に割り当てるのは割り当てのアルゴリズムが非常に難しくなるので避けたいところです。
ここではインクリメントやデクリメントが連続した命令を1命令に割り当てることで、対応させる単語を減らしました。全部で39命令。これで何とかぎりぎり対応できるレベルです。
さて、やっとたどり着きました。プログラム言語「ルイズうわああ」の命令一覧です。
‘ぅぅ’:’+++++++++’,
‘うわ’:'[‘,
‘ぁああああああああああああああああああああああん’:’>’,
‘ルイズルイズルイズ’:’++++++++’,
‘ぅううぁわぁああああ’:’>’,
‘匂い’:’+++++++++++’,
‘ぁっ’:’>’,
‘ルイ’:’+++++’,
‘フランソワーズ’:'<<<‘,
‘桃色’:’-‘,
‘ブロンド’:’]’,
‘カリカリモフモフ’:’>’,
‘ゅんきゅんきゅい’:’.’,
’12’:’>’,
‘ぁぁああ’:’++’,
‘ぁぁあああんんっ’:’.’,
‘期’:’+++++++’,
‘放送’:’..’,
‘発売’:’+++’,
‘いやぁ’:’.’,
‘ゃああああああああん’:’>’,
‘ぎゃあ’:’-‘,
‘ぐあああああああああああ’:’.’,
‘ル’:’————‘,
‘イ’:’.’,
‘い’:'<‘,
‘ゃあああああああああああああん’:’++++++++’,
‘ぁああああああああああ’:’.’,
‘ぁぁぁあああああああああ’:’——–‘,
‘ぁああああああん’:’.’,
‘ぁああああ’:’+++’,
‘え’:’.’,
‘てる’:’——‘,
‘挿絵’:’.’,
‘世の中’:’——–‘,
‘モン’:’.’,
‘ぉおおおおおおお’:’>’,
‘ケティ’:’+’,
‘ひとりでできるもん’:’.’,
繰り返しの無い部分を機械的に取り出しただけでこの狂気。さすがです。
さて、当然ですがこのプログラムにとってルイズうわああはプログラム言語に過ぎません。さっそく実行してみましょう。
入力:
ルイズ!ルイズ!ルイズ!ルイズぅぅうううわぁあああああ(中略)ハルケギニアのルイズへ届け!
出力:
Hello, World!
よし満足。誰だって理解できないものが理解できるものに置き換わったときは安心感が得られるものです。今回は無理矢理置き換えただけですが。
みなさんも、Branfu*kのインタプリタ等を用意して、上の対応表を組み込めば自前の環境でルイズうわああからHello Worldを作り出すことができます。なんなら類似の長文からもっと複雑なプログラムも実行できます。お試しあれ。
(追記: プログラム言語「ルイズうわああ」のインタプリタのソースを置いておきます。)
関連?:「進捗・どう・です・か」をランダムに表示し「進捗どうですか」が完成したら煽ってくるプログラム