gerrywastaken / toy_robot

:space_invader: A common coding test used around some parts -

Home Page:https://joneaves.wordpress.com/2014/07/21/toy-robot-coding-test/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Toy Robot

Build status

This is a simple program for moving a robot around on a platform.

Requirements

Ruby MRI version 2.3.1 is required. If you don't wish to run the specs then you can get away with 2.3.0.

Installation

> git clone https://github.com/gerrywastaken/toy_robot.git
> cd toy_robot
# Your Ruby version manager should read the .ruby-version file and set the
# version accordingly. If not you will need to set it to MRI 2.3.1
> bundle install

Usage

Input from a file

> ./toy_robot commands.txt

Standard input:

> cat commands.txt | ./toy_robot

or

> echo "PLACE 1,2,NORTH\nLEFT\nMOVE\nRIGHT\nREPORT" | ./toy_robot

Manual input:

> ./toy_robot
PLACE 1,2,NORTH
LEFT
MOVE
RIGHT
REPORT

Edited specification

The original specifications are available within full_spec.md. This file just contains a rewording of the original to group and simplify concepts.

Command support:

  • PLACE X,Y,F - puts robot on table
  • MOVE - move robot one unit forward in current facing direction
  • LEFT - face 90 degrees anti clockwise
  • RIGHT - face 90 degrees clockwise
  • REPORT - standard out, x, y and facing

Overall requirements:

  • Square Tabletop. 5 units x 5 units.
  • Ignore movement that would cause falling, including during placing.
  • Co-ordinate "0,0" is in the bottom left corner.
  • The app discards all commands until a valid PLACE.
  • Input can be from file and standard input.
  • Provide input test data

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

Assumptions and reasoning

shared_examples in tests
I want it to be explicit when two tests only differ in the test data. I use Rspec's shared_examples functionality to separate the things that change between each test, from the things that do not. In tests where this is not done, it is easy to miss that one test that is testing is a slightly different way to the tests that surround it.

While many prefer to duplicate code between tests so tests are isolated from each other, I think grouping test logic can be a huge benefit if done sparingly. However I do realize that much of this is subjective.

Simulated Polymorphism
While the `if placed?` checks could be removed from the Robot class by adding a PlacedRobot class, this will end up adding to the overall complexity and reducing readability.
Additional Fuctionality
The spec says:
The application should discard all commands in the sequence until a valid PLACE command has been executed.

If I was to strictly adhere to the discard requirement, then I would not show errors in case of invalid commands. However I felt this would hurt the end user, so I added these errors. If this functionality is not required, then it can easily be removed.

Spec wording
The spec says:
A robot that is not on the table can choose the [sic] ignore the MOVE, LEFT, RIGHT and REPORT commands.

This is contradicted by the phrase:

The application should discard all commands in the sequence until a valid PLACE command has been executed.

Typo aside, in my interpretation of the spec, I replaced can choose the with should. Trying to apply relative movements or reporting, for a robot that has not yet been placed, does not make sense. I suspect this was the original intent of the phrase.

[ss1]:

About

:space_invader: A common coding test used around some parts -

https://joneaves.wordpress.com/2014/07/21/toy-robot-coding-test/

License:GNU General Public License v3.0


Languages

Language:Ruby 97.0%Language:Dockerfile 2.7%Language:Shell 0.3%