自作Brainf*ckインタプリタを使ってAtCoderをBrainf*ckで解く


この記事は [この記事誰得？ 私しか得しないニッチな技術で記事投稿！ - Qiita](https://qiita.com/official-events/5d4f04cf2ba0cdbc8821) の参加記事です。

https://qiita.com/official-events/5d4f04cf2ba0cdbc8821

## はじめに

記事のネタに困っており、ネタ探しをしていたら

https://qiita.com/OribeYasuna/items/430e8755040433c36a47

の記事を見つけ、

**自作のBrainf\*ckインタプリタを使ってAtcoderの問題をBrainf\*ckで解こう！**

と思ってしまいました。

ここまできたらやるしかない（？）と思い、実際にやってみたので紹介します。

## 作戦

AtCoderでは、

- Bashで問題を解くことができる
- 環境にRubyがインストールされている様

なので、

1. RubyでBrainf\*ckインタプリタをつくる
2. Bashスクリプト内でRubyでつくったBrainf\*ckインタプリタを実行させる
3. Brainf\*ckのソースコード、問題で渡される標準入力をRubyの標準入力に渡す

でやることにしました。

## Brainf\*ckインタプリタをつくる

実際につくったものは以下のGistにあげてます。
この記事では詳細は省きます。

[brainfuck.rb | GitHub Gist](https://gist.github.com/ohakutsu/3f9d6829ed3a7887ab48b6aa3273e9ae)

## AtCoder解答用のBashスクリプトをつくる

作戦の通りにつくったBashスクリプトは以下です。

AtCoderの問題を解くためのBrainf\*ckのソースコードは

https://qiita.com/OribeYasuna/items/430e8755040433c36a47

のものを使わせていただきました :pray:

```bash
cat <<EOS > main.rb
class Brainfuck
  MEMORY_SIZE = 100

  def initialize
    @pc = 0
    @pointer = 0
    @memory = Array.new(MEMORY_SIZE, 0)
  end

  # @param program [String]
  def run(program)
    while @pc < program.length
      op = program[@pc]

      case op
      when '>'
        @pointer += 1
      when '<'
        @pointer -= 1
      when '+'
        @memory[@pointer] += 1
      when '-'
        @memory[@pointer] -= 1
      when '.'
        print(@memory[@pointer].chr)
      when ','
        @memory[@pointer] = \$stdin.getc.ord
      when '['
        if @memory[@pointer] == 0
          depth = 0
          while @pc < program.length
            @pc += 1

            break if depth == 0 && program[@pc] == ']'

            case program[@pc]
            when '['
              depth += 1
            when ']'
              depth -= 1
            end
          end
        end
      when ']'
        if @memory[@pointer] != 0
          depth = 0
          while @pc >= 0
            @pc -= 1

            break if depth == 0 && program[@pc] == '['

            case program[@pc]
            when ']'
              depth += 1
            when '['
              depth -= 1
            end
          end
        end
      end

      @pc += 1
    end
  end
end

brainfuck = Brainfuck.new

line = gets
brainfuck.run(line)
EOS

source=",>++++++++++++++++++++++++++++++++++++++++++++++++++++++++<>[<[->>+>+<<<]>>>[-<<<+>>>]<<>[[-]<<->>]<-]<>>>>>>>>+<<<<<<<<[[-]>+++++++++[>++++++++++<-]>-.<+++[>++++<-]>.<+++++++[>++<-]>.>>>>>>-<<<<<<<<]>>>>>>>>[[-]>,>++++++++++++++++++++++++++++++++++++++++++++++++++++++++<>[<[->>+>+<<<]>>>[-<<<+>>>]<<>[[-]<<->>]<-]<>>>>>>>>+<<<<<<<<[[-]>+++++++++[>++++++++++<-]>-.<+++[>++++<-]>.<+++++++[>++<-]>.>>>>>>-<<<<<<<<]>>>>>>>>[[-]>+++++++++++[>+++++++<-]>+.<+++[>+++++++++++<-]>.<<]<<]"

read line1

ruby main.rb <<EOS
${source}
${line1}
EOS
```

## いざ提出

結果は...

`AC`です！最高ですね！！

[提出 #43807447 - AtCoder Beginner Contest 073](https://atcoder.jp/contests/abc073/submissions/43807447)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352836/5f892a76-aa12-6cf5-bc1a-0d3c93622a4e.png)

## 最後に

無事、自作Brainf\*ckインタプリタを使ってAtCoderをBrainf\*ckで解くことができました！
自分は何をしているのだろうと思ってはいけません。楽しければよかろうなのです。

みんなでBrainf\*ck Lifeを楽しみましょう（？）