Brainf**k interpreter in Ruby I wrote this interpreter for a code challenge. Can this be written any cleaner/smaller? Could I reduce the amount of nested conditional/loops?

def brain_luck(code, input)
  output = ''
  cp = 0 # code pointer
  dp = 0 # data pointer
  ip = 0 # input pointer
  data = Array.new(10, 0)
  while cp &lt; code.length
    case code[cp]
    when '&gt;'
      dp += 1
      if dp == data.length
        data.push(0)
      end
    when '&lt;'
      dp -= 1
      if dp == -1
        dp = 0
        data.unshift(0)
      end
    when '+'
      data[dp] = (data[dp].ord+1)%256
    when '-'
      data[dp] = (data[dp].ord-1)%256
    when '.'
      output += data[dp].chr
    when ','
      data[dp] = input[ip].ord
      ip += 1
    when '['
      if data[dp] == 0
        nest_count = 1
        while nest_count &gt; 0
          case code[cp += 1]
          when '[' then nest_count += 1
          when ']' then nest_count -= 1
          end
        end
      end
    when ']' 
      if data[dp] != 0
        nest_count = 1
        while nest_count &gt; 0
          case code[cp -= 1]
          when ']' then nest_count += 1
          when '[' then nest_count -= 1
          end
        end
      end
    end
    cp += 1
  end
  output
end
Sure it can!

Steps I see to make it clean:


Create a class, define state attrs:

private

attr_reader :output, :code_pointer, :data_pointer, :input_pointer

define initialize method

def initialize(args = {})
  @code = args[:code]
  @input = args[:input]
  @output = ''
  @code_pointer, @data_pointer, @input_pointer = 0, 0, 0
end

define whens as a methods and give it right names: next_cell, prev_cell, increment, decrement, write_byte, read_byte and so on
define constant for configuration:

OPERATORS = {
  '&gt;' =&gt; :next_cell,
  '&lt;' =&gt; :prev_cell,
  '+' =&gt; :increment,
  ...
}

define method to evaluate code:

def evaluate_code
  code.each { |operator| public_send OPERATORS[operator] }
end

Finally instantiate object of your class and call evaluate_code

BrainLuck.new(code: code, input: input).evaluate_code



I think you'll love your object oriented result.