Created
January 8, 2019 14:07
-
-
Save blinry/6e8f63800cd6321d309fb4c5e6951112 to your computer and use it in GitHub Desktop.
The beginning of a Befunge interpreter for RC pairing interview
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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