Execute Brain****/Ruby: Difference between revisions
Content added Content deleted
m (moved RCBF/Ruby to Execute Brain****/Ruby) |
m (Fixed syntax highlighting.) |
||
(2 intermediate revisions by 2 users not shown) | |||
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. |
||
< |
<syntaxhighlight lang="ruby">class RCBF |
||
def initialize(program) |
def initialize(program) |
||
@d = [0] * 30_000 |
@d = [0] * 30_000 |
||
Line 13: | Line 14: | ||
jumpback_table = {} |
jumpback_table = {} |
||
jump_to = [] |
jump_to = [] |
||
@program.each_char. |
@program.each_char.with_index do |char, idx| |
||
case char |
case char |
||
when "[" then jump_to.push(idx) |
when "[" then jump_to.push(idx) |
||
Line 21: | Line 22: | ||
jumpback_table |
jumpback_table |
||
end |
end |
||
def run |
def run |
||
invert_table = @jumpback_table.invert |
|||
dc = 0 |
dc = 0 |
||
pc = 0 |
pc = 0 |
||
while pc < @program.length |
while pc < @program.length |
||
print [pc, @program[pc] |
print [pc, @program[pc]] if $DEBUG |
||
case @program[pc] |
case @program[pc] |
||
when ?> |
when ?> |
||
dc += 1 |
dc += 1 |
||
print "\t#{dc}" if $DEBUG |
print "\t#{dc}" if $DEBUG |
||
when ?< |
when ?< |
||
dc -= 1 |
dc -= 1 |
||
print "\t#{dc}" if $DEBUG |
print "\t#{dc}" if $DEBUG |
||
when ?+ |
when ?+ |
||
@d[dc] += 1 |
@d[dc] += 1 |
||
print "\t#{dc},#{@d[dc]}" if $DEBUG |
print "\t#{dc},#{@d[dc]}" if $DEBUG |
||
when ?- |
when ?- |
||
@d[dc] -= 1 |
@d[dc] -= 1 |
||
print "\t#{dc},#{@d[dc]}" if $DEBUG |
print "\t#{dc},#{@d[dc]}" if $DEBUG |
||
when ?. |
when ?. |
||
print "\t#{dc},#{@d[dc]}\t" if $DEBUG |
print "\t#{dc},#{@d[dc]}\t" if $DEBUG |
||
print @d[dc].chr |
print @d[dc].chr |
||
when ?, |
when ?, |
||
@d[dc] = $stdin.getc |
@d[dc] = $stdin.getc |
||
print "\t#{dc},#{@d[dc]}" if $DEBUG |
print "\t#{dc},#{@d[dc]}" if $DEBUG |
||
when ?[ |
when ?[ |
||
if @d[dc] == 0 |
if @d[dc] == 0 |
||
pc = |
pc = invert_table[pc] |
||
print " #{[pc,@program[pc]]}" if $DEBUG |
|||
end |
end |
||
when ?] |
when ?] |
||
if @d[dc] != 0 |
if @d[dc] != 0 |
||
pc = @jumpback_table[pc] |
pc = @jumpback_table[pc] |
||
print " #{[pc,@program[pc]]}" if $DEBUG |
|||
end |
end |
||
end |
end |
||
Line 71: | Line 73: | ||
bf = RCBF.new(helloworld) |
bf = RCBF.new(helloworld) |
||
bf.run |
bf.run |
||
# use nested loop to increment count to 64 and print (should be '@') |
# use nested loop to increment count to 64 and print (should be '@') |
||
# followed by a newline |
# followed by a newline |
||
RCBF.new('>>++++[<++++[<++++>-]>-]<<.[-]++++++++++.').run</ |
RCBF.new('>>++++[<++++[<++++>-]>-]<<.[-]++++++++++.').run</syntaxhighlight> |
||
{{out}} |
|||
Output: |
|||
<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. |
|||
<syntaxhighlight 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;')</syntaxhighlight> |
Latest revision as of 11:57, 1 September 2022
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.
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
# output 'Hello World!\n'
helloworld = <<PROGRAM
++++++++++[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.
PROGRAM
bf = RCBF.new(helloworld)
bf.run
# use nested loop to increment count to 64 and print (should be '@')
# followed by a newline
RCBF.new('>>++++[<++++[<++++>-]>-]<<.[-]++++++++++.').run
- 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.
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;')