🧠

オフラインリアルタイムどう書く E29 の実装例(BrainF**k)

2024/11/30に公開

はじめに

※本記事は、2018/12/24にQiitaに投稿した記事を移行したものです
こちらは、「オフラインリアルタイムどう書く」のBrinF**kによる実装例です。

コード

githubのレポジトリより。

solve.bf
->+>>+>>,+[
 [
  [->+>[->>>]<[>+++++++>+>]<<<<]
  >>>--[---
   <<-<<+<[-[-[-
      ** 3 **
      <<[-
       ** e==1 **
       >>>->>>[-]+>-[+[-]
        ** not slash **
        <->
       ]
       <[-
        ** slash **
        <<<<+>>>>
       ]
      <<<<<<]
      >>>[-
       ** e==0 **
       >>>>>+<[-[[-]
         ** other **
         >-<<[-]<<<<+>>>[->+<]<++++[->+++++++++++<]>>>
        ]>[-
         ** slash **
         <<<<<<+>>>>>>
        ]
       <]>[-
         ** quote **
         <<[-<<<<<+>>>>>]<[-]<++++[->+++++++++++<]<<++<<+>>>>>>>>
       ]
      <<<<<]
     ]>[-
      ** 2 **
      <<[->+>>>>-<<<<<]>[-<+>]
      >>>>[+++++[-]>+<]+>[[-]
       ** not q **
       <-<<<<++<<[-]>>>>>>>
      ]<[-
       ** q **
       <[-]<<<<[-]>+>>>>
      ]
     <<]
    <]>[-
      ** 1 **
      >>>>>+<[-[[-]
        ** other **
        >-<<[-]<<<<+<<[-]>>>>>>>
       ]>[-
        ** slash **
        <<<[-]<<<+++>>>>>>
       ]
      <]>[-
        ** quote **
        <<[-<<<<<+>>>>>]<[-]<<<++>>>>>>
      ]
    <<<<]
   <]>[-
      ** 0 **
      >>[-]>[-]>[-]
   <<<]
   >[<<<[->+<]<[->+<]<[->+<]>>>>>[-<<<<<+>>>>>]>]
  <,+>>>]
  <[
   ** newline **
   [-]<[-]>
  ]
 <<]
 <<<[-]<[->>+<<]>+>-[+[-]
  ** wrong **
  <++++[-<+++++++++>]<.
 >>]
 <[-
  ** correct **
  <-<+[-<+]->+[-.>+]
 ]
 +[[-]<+]++++++++++.[-]
->+>>+>>,+]

実行例

次のように、問題のパラメータを1行ずつファイルに登録して食わせると、答えを1行ずつ出力するようになっています。

実行例
$ cat input.txt
foo/bar/baz
/foo/bar/baz'/
"
(略)
/"/'//'/"""''//'/"'''
0gK"koYUb""S/p''z/"Et
Foo/Bar/"Hoge'/'Fuga"
$ bff solve.bf < input.txt
foo,bar,baz
-
-
(略)
-
0gKkoYUbS/p''z/Et
Foo,Bar,Hoge'/'Fuga

概要

上のコードは、次のような有限状態機械を想定して作ったものです。

本当に細かく状態を細分化すると、Start,End,Abort以外に8種類の状態となるのですが、一部を変数とすることでN,Q,Sの3状態に絞り込みました。
コード中では、Abort,N,Q,Sにそれぞれ0~3の数字を割り当てて管理しています。
※Abortを管理する必要があるのは、一旦Abortになったら延々読み捨てる必要があるから

そして変数としたのはe,qで、それぞれ次のような意味を持ちます。

  • e : 最近のスラッシュ以降、エレメントになる文字列が今の所空である ( 0: 空でない、1: 空 )
  • q : クォートの開始文字 ( シングルかダブルか )
    ※実際の処理では、文字は変則divmod8の結果で識別しており、qにはその余り部分を保持します

そのため、コード中では、文字を処理するところの左に e,q,s ( s は状態 ) の3変数を常に持ちまわるようにします。
出力する文字 ( スラッシュのところはカンマに変える ) は、順次左端に送っていって、最後に一括で出力できるようにしています。

おわりに

正規表現で処理できるんだから、BrainF**kでも書けるよね! ということで、実装してみました。

Discussion