MATLAB Quine
Quineとは、「自分自身のコードを出力するプログラム」です。
これの難しさは、例えば
printf("hello world!");
という文字列を出力するためには、
printf("printf(\"hello world!\");");
のようなものを書けば良いのですが、こうすると作ったコードが元のコードとは変わってしまっています。そこで更に
printf("printf(\"printf(\"hello world!\");\");");
としたくなるのですが、これもまた元のコードではありません。
この操作を繰り返していくとコードは無限に長くなってしまうため、一見Quineは作成不可能に見えるのですが、チューリング完全な言語には、必ずQuineが存在するという、クリーネの再帰定理が存在します。
クリーネの再帰定理+ Quine が書けることの証明 - まめめも
MATLABで書いてみる
ただのRubyのコードの翻訳なのですが、MATLABでquineを書いてみました。
こちらのサイトに、RubyにおけるQuineがありました。
Quine - Rosetta Code
これをMATLABに書き直すと、次のようになります。
x = 'x = %s; fprintf(x,[char(39) x char(39)])'; fprintf(x,[char(39) x char(39)])
ワークスペースを汚染しないために、更に無名関数による局所変数を用いると、(MATLABの無名関数内で条件分岐・複数行実行を行う方法 - woodrush’s diary参照)
feval(@(x)fprintf(x,[char(39) x char(39)]), 'feval(@(x)fprintf(x,[char(39) x char(39)]), %s)')
と書くことができます。
結果を文字列で返すには、fprintfをsprintfに変えて
feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)')
とすれば良いです。この場合、入力文字列をプログラムとして実行するeval関数を使うことで、
>> feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)') ans = feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)') >> eval(feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)')) ans = feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)') >> eval(eval(eval(eval(feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)'))))) ans = feval(@(x)sprintf(x,[char(39) x char(39)]), 'feval(@(x)sprintf(x,[char(39) x char(39)]), %s)')
となり、「プログラムの出力文字列を実行」する操作を永遠に続けることができ、ちゃんとこのコードがquineになっていることが確認できます。
更に、エンコード方法を変えると
feval(@(x)sprintf(char(x-5),[char(39) x char(39)]), 'kj{fq-E-}.xuwnsyk-hmfw-}2:.1`hmfw-8>.%}%hmfw-8>.b.1%*x.')
のようなquineを作ることもできます。
他のMATLABのquineを探していたところ、こちらの記事に、かなり短いMATLABにおけるquineを見つけました。
Quines - From Here to There
また、Quineと言えばYusuke Endoh氏の山手Quineがかなり凄いです。
山手 quine - まめめも