ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# Greycoat21's solution

## to Robot Simulator in the Delphi Pascal Track

Published at Jan 27 2020 · 0 comments
Instructions
Test suite
Solution

Write a robot simulator.

A robot factory's test facility needs a program to verify robot movements.

The robots have three possible movements:

• turn right
• turn left

Robots are placed on a hypothetical infinite grid, facing a particular direction (north, east, south, or west) at a set of {x,y} coordinates, e.g., {3,8}, with coordinates increasing to the north and east.

The robot then receives a number of instructions, at which point the testing facility verifies the robot's new position, and in which direction it is pointing.

• The letter-string "RAALAL" means:
• Turn right
• Turn left
• Turn left yet again
• Say a robot starts at {7, 3} facing north. Then running this stream of instructions should leave it at {9, 4} facing west.

## Testing

In order to run the tests for this track, you will need to install DUnitX. Please see the installation instructions for more information.

If Delphi is properly installed, and `*.dpr` file types have been associated with Delphi, then double clicking the supplied `*.dpr` file will start Delphi and load the exercise/project. `control + F9` is the keyboard shortcut to compile the project or pressing `F9` will compile and run the project.

Alternatively you may opt to start Delphi and load your project via. the `File` drop down menu.

### When Questions Come Up

We monitor the Pascal-Delphi support room on gitter.im to help you with any questions that might arise.

### Submitting Exercises

Note that, when trying to submit an exercise, make sure the exercise file you're submitting is in the `exercism/delphi/<exerciseName>` directory.

For example, if you're submitting `ubob.pas` for the Bob exercise, the submit command would be something like `exercism submit <path_to_exercism_dir>/delphi/bob/ubob.pas`.

## Source

Inspired by an interview question at a famous company.

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you may request help from a mentor.

### uRobotSimulatorTests.pas

``````unit uRobotSimulatorTests;

interface
uses
DUnitX.TestFramework;

const
CanonicalVersion = '3.1.0.1';

type
[TestFixture]
TRobotSimTest = class(TObject)
public
[Test]
//    [Ignore('Comment the "[Ignore]" statement to run the test')]
procedure Robots_are_created_with_a_position_and_direction;

[Test]
[Ignore]
procedure Negative_positions_are_allowed;

[Test]
[Ignore]
procedure changes_the_direction_from_north_to_east;

[Test]
[Ignore]
procedure changes_the_direction_from_east_to_south;

[Test]
[Ignore]
procedure changes_the_direction_from_south_to_west;

[Test]
[Ignore]
procedure changes_the_direction_from_west_to_north;

[Test]
[Ignore]
procedure changes_the_direction_from_north_to_west;

[Test]
[Ignore]
procedure changes_the_direction_from_west_to_south;

[Test]
[Ignore]
procedure changes_the_direction_from_south_to_east;

[Test]
[Ignore]
procedure changes_the_direction_from_east_to_north;

[Test]
[Ignore]
procedure increases_the_y_coordinate_one_when_facing_north;

[Test]
[Ignore]
procedure decreases_the_y_coordinate_by_one_when_facing_south;

[Test]
[Ignore]
procedure increases_the_x_coordinate_by_one_when_facing_east;

[Test]
[Ignore]
procedure decreases_the_x_coordinate_by_one_when_facing_west;

[Test]
[Ignore]

[Test]
[Ignore]
procedure instructions_to_move_west_and_north;

[Test]
[Ignore]
procedure instructions_to_move_west_and_south;

[Test]
[Ignore]
procedure instructions_to_move_east_and_north;
end;

implementation
uses uRobotSimulator;

procedure TRobotSimTest.Negative_positions_are_allowed;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(-1, -1);
Actual := TRobotSimulator.Create(TDirection.south, TCoordinate.Create(-1, -1));
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.south, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.Robots_are_created_with_a_position_and_direction;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.north, TCoordinate.Create(0, 0));
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.north, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.decreases_the_x_coordinate_by_one_when_facing_west;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(-1, 0);
Actual := TRobotSimulator.Create(TDirection.west, TCoordinate.Create(0, 0));
Actual.move('A');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.west, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.decreases_the_y_coordinate_by_one_when_facing_south;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, -1);
Actual := TRobotSimulator.Create(TDirection.south, TCoordinate.Create(0, 0));
Actual.move('A');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.south, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.increases_the_x_coordinate_by_one_when_facing_east;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(1, 0);
Actual := TRobotSimulator.Create(TDirection.east, TCoordinate.Create(0, 0));
Actual.move('A');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.east, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.increases_the_y_coordinate_one_when_facing_north;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 1);
Actual := TRobotSimulator.Create(TDirection.north, TCoordinate.Create(0, 0));
Actual.move('A');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.north, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_east_to_south;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.east, TCoordinate.Create(0, 0));
Actual.move('R');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.south, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_north_to_east;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.north, TCoordinate.Create(0, 0));
Actual.move('R');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.east, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_south_to_west;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.south, TCoordinate.Create(0, 0));
Actual.move('R');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.west, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_west_to_north;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.west, TCoordinate.Create(0, 0));
Actual.move('R');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.north, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_east_to_north;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.east, TCoordinate.Create(0, 0));
Actual.move('L');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.north, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_north_to_west;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.north, TCoordinate.Create(0, 0));
Actual.move('L');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.west, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_south_to_east;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.south, TCoordinate.Create(0, 0));
Actual.move('L');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.east, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.changes_the_direction_from_west_to_south;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(0, 0);
Actual := TRobotSimulator.Create(TDirection.west, TCoordinate.Create(0, 0));
Actual.move('L');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.south, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.instructions_to_move_east_and_north;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(11, 5);
Actual := TRobotSimulator.Create(TDirection.south, TCoordinate.Create(8, 4));
Actual.move('LAAARRRALLLL');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.north, Actual.Direction);
Actual.DisposeOf;
end;

var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(9, 4);
Actual := TRobotSimulator.Create(TDirection.North, TCoordinate.Create(7, 3));
Actual.move('RAALAL');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.west, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.instructions_to_move_west_and_north;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(-4, 1);
Actual := TRobotSimulator.Create(TDirection.North, TCoordinate.Create(0, 0));
Actual.move('LAAARALA');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.west, Actual.Direction);
Actual.DisposeOf;
end;

procedure TRobotSimTest.instructions_to_move_west_and_south;
var
Actual : TRobotSimulator;
ExpectedCoord: TCoordinate;
begin
ExpectedCoord := TCoordinate.Create(-3, -8);
Actual := TRobotSimulator.Create(TDirection.east, TCoordinate.Create(2, -7));
Actual.move('RRAAAAALA');
Assert.AreEqual(ExpectedCoord, Actual.Coordinate);
Assert.AreEqual(TDirection.south, Actual.Direction);
Actual.DisposeOf;
end;

initialization
TDUnitX.RegisterTestFixture(TRobotSimTest);
end.``````
``````unit uRobotSimulator;

interface

type
TDirection = (North, East, South, West);

TCoordinate = record
x, y: Integer;
constructor Create(x, y: Integer);
class operator Implicit(Coordinate: TCoordinate): string;
end;

TRobotSimulator = class
Coordinate: TCoordinate;
Direction: TDirection;
constructor Create(Direction: TDirection; Coordinate: TCoordinate);
procedure Move(CommandCodes: string);
end;

implementation

uses
SysUtils;

{ TCoordinate }

constructor TCoordinate.Create(x, y: Integer);
begin
Self.x := x;
Self.y := y;
end;

class operator TCoordinate.Implicit(Coordinate: TCoordinate): string;
begin
Result := IntToStr(Coordinate.x) + IntToStr(Coordinate.y);
end;

{ TRobotSimulator }

constructor TRobotSimulator.Create(
Direction: TDirection;
Coordinate: TCoordinate);
begin
Self.Coordinate := Coordinate;
Self.Direction := Direction;
end;

type
Command = class
const
TurnLeft: Char = 'L';
TurnRight: Char = 'R';
end;

procedure TRobotSimulator.Move(CommandCodes: string);

procedure Move(CommandCode: Char);
begin
if CommandCode = Command.Advance then begin
case Direction of
North: Coordinate.y := Coordinate.y + 1;
East: Coordinate.x := Coordinate.x + 1;
South: Coordinate.y := Coordinate.y - 1;
West: Coordinate.x := Coordinate.x - 1;
end;
end else if CommandCode = Command.TurnLeft then begin
Direction := TDirection((Ord(Direction) + 3) mod 4);
end else if CommandCode = Command.TurnRight then begin
Direction := TDirection((Ord(Direction) + 1) mod 4);
end;
end;

begin
for var CommandCode in CommandCodes do
Move(CommandCode);
end;

end.``````