Skip to content

Instantly share code, notes, and snippets.

@blinry
Created January 8, 2019 14:07
Show Gist options
  • Save blinry/6e8f63800cd6321d309fb4c5e6951112 to your computer and use it in GitHub Desktop.
Save blinry/6e8f63800cd6321d309fb4c5e6951112 to your computer and use it in GitHub Desktop.
The beginning of a Befunge interpreter for RC pairing interview
# A Befunge interpreter written in Ruby
# Language specification: https://github.com/catseye/Befunge-93/blob/master/doc/Befunge-93.markdown
class ProgramCounter
attr_accessor :x, :y, :dir
def initialize x, y, dir
@x, @y, @dir = x, y, dir
end
end
class Befunge
def initialize text
@pc = ProgramCounter.new(0, 0, :right)
@playfield = text.split("\n").map do |line|
symbols = line.split("")
end
@height = @playfield.length
@width = @playfield.map(&:length).max
# fill up rows to maximal length
@playfield.each do |row|
while row.length < @width
row << " "
end
end
end
def run
loop do
print_state
if interpret_command == :quit
return
end
move_program_counter
sleep 0.5
end
end
def print_state
output = ""
@playfield.each_with_index do |row, y|
row.each_with_index do |symbol, x|
if @pc.x == x and @pc.y == y
output << "("
elsif @pc.x == x-1 and @pc.y == y
output << ")"
else
output << " "
end
output << symbol
end
if @pc.x == @width-1 and @pc.y == y
output << ")"
else
output << " "
end
output << "\n"
end
output << "-"*@width*2
puts output
STDOUT.flush
end
def interpret_command
command = @playfield[@pc.y][@pc.x]
case command
when " "
# do nothing
when "<"
@pc.dir = :left
when ">"
@pc.dir = :right
when "^"
@pc.dir = :up
when "v"
@pc.dir = :down
when "@"
:quit
end
end
def move_program_counter
case @pc.dir
when :left
@pc.x -= 1
when :right
@pc.x += 1
when :up
@pc.y -= 1
when :down
@pc.y += 1
end
# wrap around, if necessary
@pc.x = @pc.x % @width
@pc.y = @pc.y % @height
end
end
# ^, >, v, and < change PC direction
# @ ends program
maze = <<HERE
>v
v>
< ^
@ >
HERE
Befunge.new(maze).run
# digits are pushed on the stack
# . outputs top stack value as int, followed by a space
# ? moves PC in a random direction
# '#' skips over next command
# +, -, *, /, and % do calculations on top two stack values, bottom value first
# ~ input ASCII value of next char
# & input int until next space
# $ pops top stack value
# : duplicates top stack value
# \ swaps top two stack values
# _ horizontal if: left if top element is non-zero, else right
# | vertical if: up if top element is non-zero, else down
# ! negates top value
# ` replaces two stack values with 1, if bottom > top, 0 otherwise
# " toggles stringmode: all character cells will have their ASCII value pushed onto the stack until another " is encountered
# , outputs top element as char
# g gets value at (x, y), determined by top two stack values
# p writes third-top stack value to (x, y), determined by top two stack values
# final challenge :D
life = <<HERE
v>>31g> ::51gg:2v++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9p BXY|-+<v3*89<%+ * * +
21 >98 *7^>+\-0|<+ * * +
*5 ^:+ 1pg15\,:< + * *** +
10^ <>$25*,51g1v+ +
-^ p<| -*46p15:+<+ +
> 31^> 151p>92*4v+ +
^_ ".", ^ vp1<+ +
>v >41p >0 v+ +
:5! vg-1g15-1g14<+ +
+1-+>+41g1-51gg+v+ +
1p-1vg+1g15-1g14<+ +
g61g>+41g51g1-g+v+ +
14*1v4+g+1g15g14<+ * * +
5>^4>1g1+51g1-g+v+ * * +
^ _^v4+gg15+1g14<+ *** +
>v! >1g1+51g1+g+v+ +
g8-v14/*25-*4*88<+ +
19+>g51gg" "- v + +
4*5 v< v-2:_3v+ +
>^ |!-3_$ v<-+ +
^ < < <|<+ ***+
>g51gp ^ >51gp^>v+ +
^14"+"< ^g14"!"<++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
HERE
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment