この広告は、90日以上更新していないブログに表示しています。
Ruby の正規表現だけでBrainfuckインタプリタを作ることができました。正規表現の実行は =~ だけなので、ループなども正規表現の内部で実行してます。
https://github.com/shinh/hack/blob/master/bf_rb_reg/bf.rb
つまりどういうことができるかというと、 BF_REG というRegexp と BF_SUFFIX という文字列定数があって、 bf という文字列に格納されたBrainfuck のコードを
BF_REG =~ bf +BF_SUFFIX
で実行することができます。出力は $~['o0'], $~['o1'], ... に入っているので、
output =''256.timesdo |i| o =$~["o#{i}"]breakif !o output += oend
的なコードで取り出すことができます。入力は ! の後に続いてる文字列を入力とする形式。Ruby の正規表現は Turing 完全でないので、無限ループはできないようになっています。
仕様の一覧を並べると
など。256まで、という制限は実装をラクにするためなので、本質的な制限ではないです、が無限にはできないです(入力文字数は無限にできるかも?)。この程度の制限があっても十分に実用的(?)で、例えばcal.bf も動いています。
$ echo 2016 10 | time ruby bf.rb cal.bf 1 2 3 4 5 6 7 8 9 10 11 12 13 14 1516 17 18 19 20 21 2223 24 25 26 27 28 2930 31ruby bf.rb cal.bf 1147.54s user 0.26s system 99% cpu 19:07.91 total
ただすごく遅くて、 cal.bf の実行に19分とかかかってました。1命令10msとかその程度だと思います。 + とか - が実に遅い。
こんなことできるとはつい最近まで思ってなかったのですが、 HITCON CTF で正規表現力の研鑽を積んだ結果、なんかできるような気がしてきて、やってみたらできました。
今思うに、一番重要なことは後方参照を更新できる、ということだったのかなと思います。 \g で呼び出された中にある後方参照は、呼び出されるたびに値が変わっていくという。
引用をストックしました
引用するにはまずログインしてください
引用をストックできませんでした。再度お試しください
限定公開記事のため引用できません。