Execute Brain****/Ruby: Difference between revisions

From Rosetta Code
Content added Content deleted
(improvement of the debugging output, each_with_index->with_index)
(I'm liking Ruby; concise AND tidy)
Line 1: Line 1:
{{implementation|Brainf***}}{{collection|RCBF}}
{{implementation|Brainf***}}{{collection|RCBF}}
==Version 1==
An implementation of a [[Brainf***]] interpreter in [[Ruby]].
An implementation of a [[Brainf***]] interpreter in [[Ruby]].
More effort could be made to read a program from a file or from stdin.
More effort could be made to read a program from a file or from stdin.
Line 80: Line 81:
<pre>Hello World!
<pre>Hello World!
@</pre>
@</pre>

==Version 2==
This variant converts the brainfuck into Ruby code and runs that instead.
Do note that this requires Ruby1.9.1 or later, earlier versions need a somewhat more verbose variant.

BF code may be read from a file or taken from STDIN.

<lang ruby>eval 'm=Hash.new(p=0);'+ARGF.read.gsub(
/./,
'>' => 'p+=1;',
'<' => 'p-=1;',
'+' => 'm[p]+=1;',
'-' => 'm[p]-=1;',
'[' => '(;',
']' => ')while((m[p]&=255)!=0);',
'.' => 'putc(m[p]&=255);',
',' => 'm[p]=STDIN.getc.ord if !STDIN.eof;')

Revision as of 19:57, 7 September 2015

Execute Brain****/Ruby is an implementation of Brainf***. Other implementations of Brainf***.
Execute Brain****/Ruby is part of RCBF. You may find other members of RCBF at Category:RCBF.

Version 1

An implementation of a Brainf*** interpreter in Ruby. More effort could be made to read a program from a file or from stdin.

<lang ruby>class RCBF

 def initialize(program)
   @d = [0] * 30_000
   @program = program
   @jumpback_table = read_program
 end
 
 def read_program
   jumpback_table = {}
   jump_to = []
   @program.each_char.with_index do |char, idx|
     case char
     when "[" then jump_to.push(idx)
     when "]" then jumpback_table[idx] = jump_to.pop
     end
   end
   jumpback_table
 end
 
 def run
   invert_table = @jumpback_table.invert
   dc = 0
   pc = 0
   while pc < @program.length
     print [pc, @program[pc]] if $DEBUG
     
     case @program[pc]
     when ?>
       dc += 1
       print "\t#{dc}" if $DEBUG
     when ?<
       dc -= 1
       print "\t#{dc}" if $DEBUG
     when ?+
       @d[dc] += 1
       print "\t#{dc},#{@d[dc]}" if $DEBUG
     when ?-
       @d[dc] -= 1
       print "\t#{dc},#{@d[dc]}" if $DEBUG
     when ?.
       print "\t#{dc},#{@d[dc]}\t" if $DEBUG
       print @d[dc].chr
     when ?,
       @d[dc] = $stdin.getc
       print "\t#{dc},#{@d[dc]}" if $DEBUG
     when ?[
       if @d[dc] == 0
         pc = invert_table[pc]
         print "  #{[pc,@program[pc]]}" if $DEBUG
       end
     when ?]
       if @d[dc] != 0
         pc = @jumpback_table[pc]
         print "  #{[pc,@program[pc]]}" if $DEBUG
       end
     end
     puts if $DEBUG
     pc += 1
   end
 end

end

  1. output 'Hello World!\n'

helloworld = <<PROGRAM ++++++++++[>+++++++>++++++++++>+++>+<<<<-] >++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>. PROGRAM bf = RCBF.new(helloworld) bf.run

  1. use nested loop to increment count to 64 and print (should be '@')
  2. followed by a newline

RCBF.new('>>++++[<++++[<++++>-]>-]<<.[-]++++++++++.').run</lang>

Output:
Hello World!
@

Version 2

This variant converts the brainfuck into Ruby code and runs that instead. Do note that this requires Ruby1.9.1 or later, earlier versions need a somewhat more verbose variant.

BF code may be read from a file or taken from STDIN.

<lang ruby>eval 'm=Hash.new(p=0);'+ARGF.read.gsub(

       /./,
       '>' => 'p+=1;',
       '<' => 'p-=1;',
       '+' => 'm[p]+=1;',
       '-' => 'm[p]-=1;',
       '[' => '(;',
       ']' => ')while((m[p]&=255)!=0);',
       '.' => 'putc(m[p]&=255);',
       ',' => 'm[p]=STDIN.getc.ord if !STDIN.eof;')