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

# acolburn's solution

## to Robot Simulator in the Delphi Pascal Track

Published at Feb 23 2021 · 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
private
FNorth: integer;
FEast: integer;
public
property North: integer read FNorth write FNorth;
property East: integer read FEast write FEast;
constructor Create(East, North: integer);
end;

TRobotSimulator = class
private
FCoordinate: TCoordinate;
FDirection: TDirection;
procedure left;
procedure right;
public
property Coordinate: TCoordinate read FCoordinate write FCoordinate;
property Direction: TDirection read FDirection write FDirection;
constructor Create(Direction: TDirection; initialCoordinate: TCoordinate);
procedure move(instructions: string);
end;

implementation

{ TCoordinate }

constructor TCoordinate.Create(East, North: integer);
begin
FNorth := North;
FEast := East;
end;

{ TRobotSimulator }

begin
case FDirection of
North: FCoordinate.North := FCoordinate.North + 1;
East: FCoordinate.East := FCoordinate.East + 1;
// moving south direction is negative north
South: FCoordinate.North := FCoordinate.North - 1;
// west is negative east
West: FCoordinate.East := FCoordinate.East - 1;
end;
end;

constructor TRobotSimulator.Create(Direction: TDirection;
initialCoordinate: TCoordinate);
begin
FDirection := Direction;
FCoordinate := initialCoordinate;
end;

procedure TRobotSimulator.left;
begin
if FDirection = North then
FDirection := West
else
Dec(FDirection);
end;

procedure TRobotSimulator.move(instructions: string);
var
I: integer;
begin
for I := 1 to length(instructions) do
begin
case instructions[I] of
'L': left;
'R': right;
end;
end;
end;

procedure TRobotSimulator.right;
begin
if FDirection = West then
FDirection := North
else
Inc(FDirection);
end;

end.``````