Skip to content

Instantly share code, notes, and snippets.

Created September 16, 2014 05:21
Show Gist options
  • Save anonymous/616c73d291d3d1580fad to your computer and use it in GitHub Desktop.
Save anonymous/616c73d291d3d1580fad to your computer and use it in GitHub Desktop.
require_relative 'robot'
require_relative 'string'
class ArgumentHandler
@placed = false
@interactive = false
HELP_COMMAND_LINE_ARGS = <<-EOF.shift_left
Arguments for toy-robot are in format toy-robot.rb option (PARAM).
Options are:
-i interactive
-f file Filename(s)
Examples:
- toy-robot.rb -i
- toy-robot.rb -f test-data.txt test-data2.txt
EOF
HELP_COMMANDS = <<-EOF.shift_left
Arguments taken are:
- PLACE {X},{Y},{FACE}
* X needs to be 0-3
* Y needs to be 0-3
* FACE needs to be eiter NORTH, SOUTH, EAST or WEST
- MOVE
- LEFT
- RIGHT
- REPORT
EOF
HELP_PLACING = <<-EOF.shift_left
Please place the robot on the table with PLACE {X}, {Y}, {FACE}"
* X needs to be 0-3
* Y needs to be 0-3
* FACE needs to be eiter NORTH, SOUTH, EAST or WEST
EOF
def initialize
@r = Robot.new
handle_args
end
def display_welcome
puts "Welcome to the toy robot simulator."
puts HELP_PLACING
end
def interactive
a = $stdin.gets.chomp
delegate(a)
end
def handle_args
option = ARGV.shift
a = ARGV.join
case option
when /-i/
@interactive = true
display_welcome
interactive
when /-f/
ARGF.readlines.each do |command|
puts "Command: #{command}"
delegate(command.rstrip!)
end
else
puts HELP_COMMAND_LINE_ARGS
end
end
def delegate(command)
begin
case command.upcase
when /PLACE/i
place_robot(command)
when "MOVE"
@r.move
when "LEFT"
@r.rotate_left
when "RIGHT"
@r.rotate_right
when "REPORT"
puts @r.report
when /(^EXIT$|^QUIT$)/i
abort("#{$1.capitalize}, thanks for using toy robot simulator")
when "HELP"
puts HELP_COMMANDS
else
puts "Command '#{command}' not recognized, spelling error?"
end
rescue => e
puts e.message
end
interactive if @interactive
end
def place_robot(args)
if args.match /PLACE ([0-4]{1}),[ ]*([0-4]{1}),[ ]*(NORTH|SOUTH|EAST|WEST)/i
begin
@r.place($1.to_i,$2.to_i,$3)
@placed = true
rescue => e
puts "Wrong placement:"
puts e.message
puts e.backtrace
end
else
puts "Wrong placement parameters for: '#{args}'"
puts HELP_PLACING
end
end
end
Code problem details:
-----------
Toy Robot Simulator
Description:
. The application is a simulation of a toy robot moving on a square tabletop, of dimensions 5 units x 5 units.
. There are no other obstructions on the table surface.
. The robot is free to roam around the surface of the table, but must be prevented from falling to destruction. Any movement
that would result in the robot falling from the table must be prevented, however further valid movement commands must still
be allowed.
. Create an application that can read in commands of the following form -
PLACE X,Y,F
MOVE
LEFT
RIGHT
REPORT
. PLACE will put the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.
. The origin (0,0) can be considered to be the SOUTH WEST most corner.
. The first valid command to the robot is a PLACE command, after that, any sequence of commands may be issued, in any order, including another PLACE command. The application should discard all commands in the sequence until a valid PLACE command has been executed.
. MOVE will move the toy robot one unit forward in the direction it is currently facing.
. LEFT and RIGHT will rotate the robot 90 degrees in the specified direction without changing the position of the robot.
. REPORT will announce the X,Y and F of the robot. This can be in any form, but standard output is sufficient.
. A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT and REPORT commands.
. Input can be from a file, or from standard input, as the developer chooses.
. Provide test data to exercise the application.
Constraints:
The toy robot must not fall off the table during movement. This also includes the initial placement of the toy robot.
Any move that would cause the robot to fall must be ignored.
Example Input and Output:
a)
PLACE 0,0,NORTH
MOVE
REPORT
Output: 0,1,NORTH
b)
PLACE 0,0,NORTH
LEFT
REPORT
Output: 0,0,WEST
c)
PLACE 1,2,EAST
MOVE
MOVE
LEFT
MOVE
REPORT
Output: 3,3,NORTH
Deliverables:
The Ruby source files, the test data and any test code.
It is not required to provide any graphical output showing the movement of the toy robot.
-------
# robot.rb
class Robot
PLACE_MESSAGE = "Please place the robot"
def initialize
@faces = [
{direction: "north", limit: 4, facing: true},
{direction: "west", limit: 0, facing: false, position: 0},
{direction: "south", limit: 0, facing: false, position: 0},
{direction: "east", limit: 4, facing: false}
]
@placed = false
end
def rotate_left
raise PLACE_MESSAGE unless @placed
rotate_facing(@faces)
end
def rotate_right
raise PLACE_MESSAGE unless @placed
rotate_facing(@faces.reverse)
end
def move
raise PLACE_MESSAGE unless @placed
case current_direction?
when /south|west/
@faces.find{|f| f[:direction] == current_direction?}[:position]-=1 unless position_of?(current_direction?) <= 0
when "north"
@faces.find{|f| f[:direction] == "south"}[:position]+=1 unless position_of?("south") >= limit?("north")
when "east"
@faces.find{|f| f[:direction] == "west"}[:position]+=1 unless position_of?("west") >= limit?("east")
end
end
def place(x,y,direction)
begin
validate_position(x, y)
validate_direction(direction)
set_position("west", x)
set_position("south", y)
set_direction(direction)
@placed = true
rescue
raise
end
end
def report
raise PLACE_MESSAGE unless @placed
return %Q{#{position_of? "west"}, #{position_of? "south"}, #{current_direction?.upcase}}
end
private
def rotate_facing(hash)
found_facing = false
hash.each_with_index do |f, i|
if f[:facing] == true
f[:facing] = false
if i == hash.length-1
hash[0][:facing] = true
break
else
hash[i+1][:facing] = true
break
end
end
end
end
def validate_direction(direction)
case direction.downcase
when "north"
true
when "south"
true
when "east"
true
when "west"
true
else
raise "Invalid direction"
end
end
def set_direction(direction)
direction.downcase!
@faces.each{|f| f[:facing] = false}
@faces.find{|f| f[:direction] == direction}[:facing] = true
end
def set_position(direction, position)
@faces.find{|f| f[:direction] == direction}[:position] = position
end
def validate_position(x, y)
raise "Invalid horiontal position" if (x > limit?("east") or x < limit?("west"))
raise "Invalid vertical position" if (y > limit?("north") or y < limit?("south"))
end
def current_direction?
@faces.find{|f| f[:facing] == true}[:direction]
end
def position_of?(direction)
@faces.find{|f| f[:direction] == direction}[:position]
end
def limit?(direction)
@faces.find{|f| f[:direction] == direction.downcase}[:limit]
end
end
# FOR test driven development:
#SPEC FILE, robot.spec:
require_relative'robot'
describe "place" do
it "places robot based on parameters" do
r = Robot.new
r.place(2,2, "North")
expect {r.place(2, 2, "Norte")}.to raise_error
expect {r.place(10, 0, "North")}.to raise_error
expect {r.place(0, 10, "North")}.to raise_error
expect {r.place(-2, 0, "North")}.to raise_error
expect {r.place(0, -2, "North")}.to raise_error
expect {r.place(10, 10, "North")}.to raise_error
end
end
describe "report" do
it "Reports position and direction of robot" do
r = Robot.new
r.place(2,2, "North")
expect(r.report).to eq("2, 2, NORTH")
end
end
describe "move" do
it "Moves robot" do
r = Robot.new
expect(r.report).to eq("0, 0, NORTH")
r.move
expect(r.report).to eq("0, 1, NORTH")
r.move
expect(r.report).to eq("0, 2, NORTH")
r.place(2,2,"East")
r.move
expect(r.report).to eq("3, 2, EAST")
r.place(0,0,"SOUTH")
r.move
expect(r.report).to eq("0, 0, SOUTH")
r.place(2,2,"NORTH")
10.times{r.move}
expect(r.report).to eq("2, 4, NORTH")
end
end
describe "rotate" do
it "Rotates robot" do
r = Robot.new
r.rotate_left
expect(r.report).to eq("0, 0, WEST")
r.rotate_left
expect(r.report).to eq("0, 0, SOUTH")
r.rotate_left
expect(r.report).to eq("0, 0, EAST")
r.rotate_left
expect(r.report).to eq("0, 0, NORTH")
r.rotate_right
expect(r.report).to eq("0, 0, EAST")
r.rotate_right
expect(r.report).to eq("0, 0, SOUTH")
r.rotate_right
expect(r.report).to eq("0, 0, WEST")
r.rotate_right
expect(r.report).to eq("0, 0, NORTH")
end
end
class String
def shift_left
gsub /^\t/, ''
end
end
report
re
place 2,2,f
place 2, 2, norte
place 2,5, north
place 2,2,north
move
move
right
move
report
right
move
move
move
move
report
left
move
move
left
move
report
move
left
report
move
move
move
report
Command: report
Please place the robot
Command: re
Command 're' not recognized, spelling error?
Command: place 2,2,f
Wrong placement parameters for: 'place 2,2,f'
Please place the robot on the table with PLACE {X}, {Y}, {FACE}"
* X needs to be 0-3
* Y needs to be 0-3
* FACE needs to be eiter NORTH, SOUTH, EAST or WEST
Command: place 2, 2, norte
Wrong placement parameters for: 'place 2, 2, norte'
Please place the robot on the table with PLACE {X}, {Y}, {FACE}"
* X needs to be 0-3
* Y needs to be 0-3
* FACE needs to be eiter NORTH, SOUTH, EAST or WEST
Command: place 2,5, north
Wrong placement parameters for: 'place 2,5, north'
Please place the robot on the table with PLACE {X}, {Y}, {FACE}"
* X needs to be 0-3
* Y needs to be 0-3
* FACE needs to be eiter NORTH, SOUTH, EAST or WEST
Command: place 2,2,north
Command: move
Command: move
Command: right
Command: move
Command: report
3, 4, EAST
Command: right
Command: move
Command: move
Command: move
Command: move
Command: report
3, 0, SOUTH
Command: left
Command: move
Command: move
Command: left
Command: move
Command: report
4, 1, NORTH
Command: move
Command: left
Command: report
4, 2, WEST
Command: move
Command: move
Command: move
Command: report
1, 2, WEST
#!/usr/bin/env ruby
##
# Toy robot simulator
# Some licensing things normally here
##
ArgumentHandler.new.handle_args
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment