# Brainf*ck interpreter struct Tape def initialize @tape = [0] @pos = 0 end def get @tape[@pos] end def inc @tape[@pos] += 1 end def dec @tape[@pos] -= 1 end def advance @pos += 1 @tape << 0 if @tape.size <= @pos end def devance @pos -= 1 raise "pos should be > 0" if @pos < 0 end def set(value) @tape[@pos] = value end end class Program def initialize(@chars : Array(Char), @bracket_map : Hash(Int32, Int32)) end def run tape = Tape.new pc = 0 while pc < @chars.size case @chars[pc] when '>'; tape.advance when '<'; tape.devance when '+'; tape.inc when '-'; tape.dec when '.'; print tape.get.chr when ','; STDIN.read_byte.try { |byte| tape.set byte.to_i } when '['; pc = @bracket_map[pc] if tape.get == 0 when ']'; pc = @bracket_map[pc] if tape.get != 0 else # skip end pc += 1 end end def self.parse(text) parsed = [] of Char bracket_map = {} of Int32 => Int32 leftstack = [] of Int32 pc = 0 text.each_char do |char| if "[]<>+-,.".includes?(char) parsed << char if char == '[' leftstack << pc elsif char == ']' && !leftstack.empty? left = leftstack.pop right = pc bracket_map[left] = right bracket_map[right] = left end pc += 1 end end Program.new(parsed, bracket_map) end end text = if ARGV.size > 0 File.read(ARGV[0]) else <<-PROGRAM Benchmark brainf*ck program >++[<+++++++++++++>-]<[[>+>+<<-]>[<+>-]++++++++ [>++++++++<-]>.[-]<<>++++++++++[>++++++++++[>++ ++++++++[>++++++++++[>++++++++++[>++++++++++[>+ +++++++++[-]<-]<-]<-]<-]<-]<-]<-]++++++++++. PROGRAM end Program.parse(text).run