Skip to content

Commit e632750

Browse files
committed
Optimise HandleInput#interpret method. Update specs and readme
1 parent e921af6 commit e632750

File tree

6 files changed

+91
-105
lines changed

6 files changed

+91
-105
lines changed

README.md

Lines changed: 35 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
11
# Toy Robot
22
Toy robot simulator written in Ruby
33

4-
## Table of Contents
5-
1. [Installation](#Installation)
6-
2. [Usage](#Usage)
7-
3. [Testing](#Testing)
8-
4. [Design](#Design)
9-
5. [Specifications](#Specifications)
4+
***
105

116
## Installation
127
Environment: Built on Mac OSx using Ruby -v 2.4.1
@@ -20,78 +15,77 @@ Clone this Repo
2015
In root of the app run bundle install
2116
> $ gem install bundler && bundle install
2217
18+
***
19+
2320
## Usage
2421
Run the program from the app root
2522
> $ toy_robot.rb
26-
23+
2724
Expected terminal output:
2825
> Options: PLACE X,Y,F; MOVE; LEFT; RIGHT; REPORT; EXIT
2926
30-
Available commands
31-
| Command | Description |
32-
| ------------- | ------------- |
33-
| PLACE X,Y,F | Place the robot on the table at coordinates x,y and facing the direction f. Valid x andy values are between 0-4. Valid directions are WEST, NORTH, EAST, SOUTH. Example Input: "PLACE 0,0,NORTH"|
34-
| MOVE | Move the robot forward 1 step in the direction it is facing. |
35-
| LEFT | Turn the robot's direction 90 degress to the left. I.e. if the robot is facing NORTH, 1 left turn will turn the robot's direction to WEST. |
36-
| RIGHT | Turn the robot's direction 90 degress to the right. I.e. if the robot is facing NORTH, 1 left turn will turn the robot's direction to EAST. |
37-
| REPORT | Output the current position of the robot. Example Output: "Output: 0,0,NORTH" |
38-
| EXIT | Gracefully exit the program. |
27+
Commands | Description
28+
--- | ---
29+
PLACE X,Y,F | Place the robot on the table at coordinates x,y and facing the direction f. Valid x andy values are between 0-4. Valid directions are WEST, NORTH, EAST, SOUTH. Example Input: "PLACE 0,0,NORTH"
30+
MOVE | Move the robot forward 1 step in the direction it is facing.
31+
LEFT | Turn the robot's direction 90 degress to the left. I.e. if the robot is facing NORTH, 1 left turn will turn the robot's direction to WEST.
32+
RIGHT | Turn the robot's direction 90 degress to the right. I.e. if the robot is facing NORTH, 1 left turn will turn the robot's direction to EAST.
33+
REPORT | Output the current position of the robot. Example Output: "Output: 0,0,NORTH"
34+
EXIT | Gracefully exit the program.
35+
36+
***
3937

4038
## Testing
4139
Test by running rspec http://rspec.info/
4240
> $ bundle exec rspec
4341
4442
Expected terminal output:
45-
> ... ..Output: 0,0,NORTH
46-
>
47-
> ... ... ... ...Output: 1,2,NORTH
43+
> ... ... ... ... ... .Output: 1,2,NORTH
4844
>
49-
> ... ... ... ... ... ...
45+
> ... ... ... ... ... ... .
5046
>
5147
> Finished in 0.01938 seconds (files took 0.23698 seconds to load)
5248
>
5349
> 35 examples, 0 failures
5450
55-
## Speicifications
56-
__Description:__
51+
***
52+
53+
## Specifications
54+
### Description
5755

5856
The application is a simulation of a toy robot moving on a square tabletop, of dimensions 5 units x 5 units.
5957

6058
There are no other obstructions on the table surface.
6159

6260
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.
6361

64-
Create an application that can read in commands of the following form -
62+
Create an application that can read in commands of the following form - PLACE X,Y,F | MOVE | LEFT | RIGHT | REPORT
6563

66-
* PLACE X,Y,F
64+
__PLACE__
6765

68-
* MOVE
66+
* Will put the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.
6967

70-
* LEFT
68+
* The origin (0,0) can be considered to be the SOUTH WEST most corner.
7169

72-
* RIGHT
70+
* The first valid command to the robot is a PLACE command, aXer 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.
7371

74-
* REPORT
75-
76-
PLACE will put the toy robot on the table in position X,Y and facing NORTH, SOUTH, EAST or WEST.
72+
__MOVE__
7773

78-
The origin (0,0) can be considered to be the SOUTH WEST most corner.
74+
* Will move the toy robot one unit forward in the direction it is currently facing.
7975

80-
The first valid command to the robot is a PLACE command, aXer 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.
76+
__LEFT and RIGHT__
8177

82-
MOVE will move the toy robot one unit forward in the direction it is currently facing.
78+
* Will rotate the robot 90 degrees in the specified direction without changing the position of the robot.
8379

84-
LEFT and RIGHT will rotate the robot 90 degrees in the specified direction without changing the position of the robot.
80+
__REPORT__
8581

86-
REPORT will announce the X,Y and F of the robot. This can be in any form, but standard output is sufficient.
82+
* Will announce the X,Y and F of the robot. This can be in any form, but standard output is sufficient.
8783

88-
A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT
89-
90-
and REPORT commands.
84+
* A robot that is not on the table can choose the ignore the MOVE, LEFT, RIGHT and REPORT commands.
9185

92-
Input can be from a file, or from standard input, as the developer chooses. . Provide test data to exercise the application.
86+
* Input can be from a file, or from standard input, as the developer chooses. . Provide test data to exercise the application.
9387

94-
__Constraints:__
88+
### Constraints
9589

9690
The toy robot must not fall off the table during movement. This also includes the initial placement of the toy robot.
9791
Any move that would cause the robot to fall must be ignored.
@@ -130,8 +124,7 @@ c)
130124
>
131125
> Output: 3,3,NORTH
132126
133-
__Deliverables:__
127+
### Deliverables
134128

135129
The source files, the test data and any test code.
136130
It is not required to provide any graphical output showing the movement of the toy robot.
137-

lib/action.rb

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
# Action class
22
class Action
3-
attr_reader :robot
4-
5-
def initialize(robot)
6-
@robot = robot
7-
end
8-
93
# Place method
104
# @param command [String]
115
# @return Position
@@ -51,6 +45,8 @@ def right(position)
5145
def report(position)
5246
message = "Output: #{position.x},#{position.y},#{position.f} \n"
5347
$stdout.print message
48+
49+
position
5450
end
5551

5652
private

lib/handle_input.rb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@ class HandleInput
66

77
# Command Options
88
PLACE = /^PLACE\s+\d+\s*,\s*\d+\s*,\s*(WEST||NORTH||EAST||SOUTH)$/
9-
MOVE = /^MOVE$/
10-
LEFT = /^LEFT$/
11-
RIGHT = /^RIGHT$/
12-
REPORT = /^REPORT$/
9+
ACTIONS = %w[MOVE LEFT RIGHT REPORT].freeze
1310

1411
def initialize(robot, table, action)
1512
@robot = robot
@@ -21,17 +18,23 @@ def initialize(robot, table, action)
2118
# @param command [String]
2219
# @return Position
2320
def interpret(command)
24-
return exec(action.place(command)) if PLACE.match?(command)
21+
return unless command.match(PLACE) || ACTIONS.include?(command)
2522

23+
return exec(action.place(command)) if command.match?(PLACE)
2624
return if robot.not_in_place?
2725

28-
return exec(action.move(robot.position)) if MOVE.match?(command)
29-
30-
return exec(action.left(robot.position)) if LEFT.match?(command)
26+
exec(next_position(robot.position, command))
27+
end
3128

32-
return exec(action.right(robot.position)) if RIGHT.match?(command)
29+
private
3330

34-
return action.report(robot.position) if REPORT.match?(command)
31+
# Next position method
32+
# Find the robot's next position if an action was to be performed
33+
# @param position [Object]
34+
# @param command [String]
35+
# @return Position
36+
def next_position(position, command)
37+
action.public_send ACTIONS.detect { |e| e == command }.downcase, position
3538
end
3639

3740
# Exec method

spec/action_spec.rb

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,9 @@
33
require './lib/action'
44

55
describe Action do
6-
describe '#initialize' do
7-
it 'should have a current_position attribute which is nil' do
8-
instance = Action.new(@robot)
9-
10-
expect(instance.robot).to be_nil
11-
end
12-
end
13-
146
describe '#place' do
157
it 'should return an instance of Position' do
16-
instance = Action.new(@robot)
8+
instance = Action.new
179
command = 'PLACE 0,0,NORTH'
1810

1911
expect(instance.place(command)).to be_a Position
@@ -22,7 +14,7 @@
2214

2315
describe '#move' do
2416
it 'should return an instance of Position' do
25-
instance = Action.new(@robot)
17+
instance = Action.new
2618
position = Position.new(0, 0, 'NORTH')
2719

2820
expect(instance.move(position)).to be_a Position
@@ -31,7 +23,7 @@
3123

3224
describe '#left' do
3325
it 'should return an instance of Position' do
34-
instance = Action.new(@robot)
26+
instance = Action.new
3527
position = Position.new(0, 0, 'NORTH')
3628

3729
expect(instance.left(position)).to be_a Position
@@ -40,47 +32,47 @@
4032

4133
describe '#right' do
4234
it 'should return an instance of Position' do
43-
instance = Action.new(@robot)
35+
instance = Action.new
4436
position = Position.new(0, 0, 'NORTH')
4537

4638
expect(instance.right(position)).to be_a Position
4739
end
4840
end
4941

5042
describe '#report' do
51-
it 'should return nil' do
52-
instance = Action.new(@robot)
43+
it 'should return an instance of Position' do
44+
instance = Action.new
5345
position = Position.new(0, 0, 'NORTH')
5446

55-
expect(instance.report(position)).to be_nil
47+
expect(instance.right(position)).to be_a Position
5648
end
5749
end
5850

5951
describe '#prev_option' do
6052
it 'should return the previous value in the OPTIONS array' do
61-
instance = Action.new(@robot)
53+
instance = Action.new
6254

6355
expect(instance.send(:prev_option, 'NORTH')).to be_a String
6456
expect(instance.send(:prev_option, 'NORTH')).to eq 'WEST'
6557
end
6658

6759
it 'should return nil if the direction param is empty' do
68-
instance = Action.new(@robot)
60+
instance = Action.new
6961

7062
expect(instance.send(:prev_option, '')).to be_nil
7163
end
7264
end
7365

7466
describe '#next_option' do
7567
it 'should return the next value in the OPTIONS array' do
76-
instance = Action.new(@robot)
68+
instance = Action.new
7769

7870
expect(instance.send(:next_option, 'NORTH')).to be_a String
7971
expect(instance.send(:next_option, 'NORTH')).to eq 'EAST'
8072
end
8173

8274
it 'should return nil if the direction param is empty' do
83-
instance = Action.new(@robot)
75+
instance = Action.new
8476

8577
expect(instance.send(:next_option, '')).to be_nil
8678
end

spec/handle_input_spec.rb

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,22 @@
1818
end
1919

2020
describe '#interpret' do
21-
it 'should return an instance of Position command matches PLACE pattern' do
22-
robot = Robot.new
23-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
21+
it 'should return an instance of Position when command matches PLACE pattern' do
22+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
2423
command = 'PLACE 1,2,NORTH'
2524

2625
expect(instance.interpret(command)).to be_a Position
2726
end
2827

29-
it 'should return nil if robot is not in place' do
30-
robot = Robot.new
31-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
28+
it 'should return nil when robot is not in place' do
29+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
3230
command = ''
3331

3432
expect(instance.interpret(command)).to be_nil
3533
end
3634

37-
it 'should return an instance of Position if command matches MOVE pattern' do
38-
robot = Robot.new
39-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
35+
it 'should return an instance of Position when command matches MOVE pattern' do
36+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
4037
command1 = 'PLACE 1,2,NORTH'
4138
command2 = 'MOVE'
4239

@@ -45,9 +42,8 @@
4542
expect(instance.interpret(command2)).to be_a Position
4643
end
4744

48-
it 'should return an instance of Position if command matches LEFT pattern' do
49-
robot = Robot.new
50-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
45+
it 'should return an instance of Position when command matches LEFT pattern' do
46+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
5147
command1 = 'PLACE 1,2,NORTH'
5248
command2 = 'LEFT'
5349

@@ -56,9 +52,8 @@
5652
expect(instance.interpret(command2)).to be_a Position
5753
end
5854

59-
it 'should return an instance of Position if command matches RIGHT pattern' do
60-
robot = Robot.new
61-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
55+
it 'should return an instance of Position when command matches RIGHT pattern' do
56+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
6257
command1 = 'PLACE 1,2,NORTH'
6358
command2 = 'RIGHT'
6459

@@ -67,33 +62,40 @@
6762
expect(instance.interpret(command2)).to be_a Position
6863
end
6964

70-
it 'should return nil if command matches REPORT pattern' do
71-
robot = Robot.new
72-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
65+
it 'should return an instance of Position when command matches REPORT pattern' do
66+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
7367
command1 = 'PLACE 1,2,NORTH'
7468
command2 = 'REPORT'
7569

7670
instance.interpret(command1)
7771

78-
expect(instance.interpret(command2)).to be_nil
72+
expect(instance.interpret(command2)).to be_a Position
73+
end
74+
end
75+
76+
describe '#next_position' do
77+
it 'should return an instance of Position' do
78+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
79+
position = Position.new(0, 0, 'NORTH')
80+
command = 'MOVE'
81+
82+
expect(instance.send(:next_position, position, command)).to be_a Position
7983
end
8084
end
8185

8286
describe '#exec' do
8387
it 'should return an instance of Position if position is a valid table position' do
84-
robot = Robot.new
85-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
88+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
8689
position = Position.new(0, 0, 'NORTH')
8790

88-
expect(instance.exec(position)).to be_a Position
91+
expect(instance.send(:exec, position)).to be_a Position
8992
end
9093

9194
it 'should return nil if position is not a valid table position' do
92-
robot = Robot.new
93-
instance = HandleInput.new(robot, Table.new, Action.new(robot))
95+
instance = HandleInput.new(Robot.new, Table.new, Action.new)
9496
position = Position.new(0, 6, 'NORTH')
9597

96-
expect(instance.exec(position)).to be_nil
98+
expect(instance.send(:exec, position)).to be_nil
9799
end
98100
end
99101
end

0 commit comments

Comments
 (0)