Skip to content

Instantly share code, notes, and snippets.

@drench
Last active August 10, 2017 03:30
Show Gist options
  • Save drench/6a99797c87491fe022b79eb1ed47fdb9 to your computer and use it in GitHub Desktop.
Save drench/6a99797c87491fe022b79eb1ed47fdb9 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
# https://www.meetup.com/ChicagoRuby/events/241147344/
class Grid
attr_accessor :board, :size
def initialize(size)
@size = size
@board = Array.new(size) { Array.new(size, ". ") }
end
def draw(turtle)
@board[turtle.y][turtle.x] = "X "
end
def to_s
@board.map { |row| row.join("") }
end
end
class Turtle
attr_reader :x, :y
def initialize(x, y, board)
@x = x
@y = y
@orientation = 0
@board = board
move(0)
end
def forward(n)
n.times { move(1) }
end
def backward(n)
n.times { move(-1) }
end
def rotate_left(degrees)
rotate(degrees * -1)
end
def rotate_right(degrees)
rotate(degrees)
end
def rotate(degrees)
@orientation += degrees
@orientation -= 360 if @orientation >= 360
@orientation += 360 if @orientation < 0
end
def move(direction)
if @orientation > 0 && @orientation < 180
@x += direction
elsif @orientation < 360 && @orientation > 180
@x -= direction
end
if @orientation > 270 || @orientation < 90
@y -= direction
elsif @orientation > 90 && @orientation < 270
@y += direction
end
if @x < 0
@x = @board.size - 1
elsif @x >= @board.size
@x = 0
end
if @y < 0
@y = @board.size - 1
elsif @y >= @board.size
@y = 0
end
@board.draw(self)
end
end
class TurtleRunner
attr_reader :grid
def initialize(io)
@io = io
@size = @io.readline.chomp.to_i
@grid = Grid.new(@size)
@turtle = Turtle.new(@size / 2, @size / 2, @grid)
read_instructions
end
def read_instructions
@instructions = []
@io.each_line do |line|
line = line.chomp
next unless line.match(/\w/)
command, arg = line.split(/\s+/, 2)
if command == "REPEAT"
run_repeat(arg)
else
run_command(command, arg)
end
end
end
def run_repeat(instructions)
match = /(\d+)\s+\[\s+(.+)\s\]/.match(instructions)
times = match[1].to_i
args = match[2].split.each_slice(2).to_a
times.times do
args.each { |subarg| run_command(subarg[0], subarg[1]) }
end
end
def run_command(command, arg)
case command
when "RT"
@turtle.rotate_right(arg.to_i)
when "FD"
@turtle.forward(arg.to_i)
when "BK"
@turtle.backward(arg.to_i)
when "LT"
@turtle.rotate_left(arg.to_i)
else
raise "Unknown command #{command}"
end
end
end
puts TurtleRunner.new(DATA).grid.to_s
__END__
41
RT 90
FD 10
RT 45
FD 5
REPEAT 2 [ RT 90 FD 15 ]
RT 90
FD 5
RT 45
FD 9
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment