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

# SergiiVlasiuk's solution

## to Robot Simulator in the Scala Track

Published at Aug 18 2019 · 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.

The Scala exercises assume an SBT project scheme. The exercise solution source should be placed within the exercise directory/src/main/scala. The exercise unit tests can be found within the exercise directory/src/test/scala.

To run the tests simply run the command sbt test in the exercise directory.

For more detailed info about the Scala track see the help page.

## Source

Inspired by an interview question at a famous company.

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### RobotSimulatorTest.scala

import org.scalatest.{Matchers, FunSuite}

/** @version 2.2.0 */
class RobotSimulatorTest extends FunSuite with Matchers {

test(
"A robot is created with a position and a direction - Robots are created with a position and direction") {
Robot(Bearing.North, (0, 0)) should be(Robot(Bearing.North, (0, 0)))
}

test(
"A robot is created with a position and a direction - Negative positions are allowed") {
pending
Robot(Bearing.South, (-1, -1)) should be(Robot(Bearing.South, (-1, -1)))
}

test(
"rotates the robot's direction 90 degrees clockwise - does not change the position") {
pending
Robot(Bearing.North, (0, 0)).turnRight.coordinates should be((0, 0))
}

test(
"rotates the robot's direction 90 degrees clockwise - changes the direction from north to east") {
pending
Robot(Bearing.North, (0, 0)).turnRight.bearing should be(Bearing.East)
}

test(
"rotates the robot's direction 90 degrees clockwise - changes the direction from east to south") {
pending
Robot(Bearing.East, (0, 0)).turnRight.bearing should be(Bearing.South)
}

test(
"rotates the robot's direction 90 degrees clockwise - changes the direction from south to west") {
pending
Robot(Bearing.South, (0, 0)).turnRight.bearing should be(Bearing.West)
}

test(
"rotates the robot's direction 90 degrees clockwise - changes the direction from west to north") {
pending
Robot(Bearing.West, (0, 0)).turnRight.bearing should be(Bearing.North)
}

test(
"rotates the robot's direction 90 degrees counter-clockwise - does not change the position") {
pending
Robot(Bearing.North, (0, 0)).turnLeft.coordinates should be((0, 0))
}

test(
"rotates the robot's direction 90 degrees counter-clockwise - changes the direction from north to west") {
pending
Robot(Bearing.North, (0, 0)).turnLeft.bearing should be(Bearing.West)
}

test(
"rotates the robot's direction 90 degrees counter-clockwise - changes the direction from west to south") {
pending
Robot(Bearing.West, (0, 0)).turnLeft.bearing should be(Bearing.South)
}

test(
"rotates the robot's direction 90 degrees counter-clockwise - changes the direction from south to east") {
pending
Robot(Bearing.South, (0, 0)).turnLeft.bearing should be(Bearing.East)
}

test(
"rotates the robot's direction 90 degrees counter-clockwise - changes the direction from east to north") {
pending
Robot(Bearing.East, (0, 0)).turnLeft.bearing should be(Bearing.North)
}

test(
"moves the robot forward 1 space in the direction it is pointing - does not change the direction") {
pending
}

test(
"moves the robot forward 1 space in the direction it is pointing - increases the y coordinate one when facing north") {
pending
Robot(Bearing.North, (0, 0)).advance.coordinates should be((0, 1))
}

test(
"moves the robot forward 1 space in the direction it is pointing - decreases the y coordinate by one when facing south") {
pending
Robot(Bearing.South, (0, 0)).advance.coordinates should be((0, -1))
}

test(
"moves the robot forward 1 space in the direction it is pointing - increases the x coordinate by one when facing east") {
pending
Robot(Bearing.East, (0, 0)).advance.coordinates should be((1, 0))
}

test(
"moves the robot forward 1 space in the direction it is pointing - decreases the x coordinate by one when facing west") {
pending
Robot(Bearing.West, (0, 0)).advance.coordinates should be((-1, 0))
}

test(
"Where R = Turn Right, L = Turn Left and A = Advance, the robot can follow a series of instructions and end up with the correct position and direction - instructions to move west and north") {
pending
Robot(Bearing.North, (0, 0)).simulate("LAAARALA") should be(
Robot(Bearing.West, (-4, 1)))
}

test(
"Where R = Turn Right, L = Turn Left and A = Advance, the robot can follow a series of instructions and end up with the correct position and direction - instructions to move west and south") {
pending
Robot(Bearing.East, (2, -7)).simulate("RRAAAAALA") should be(
Robot(Bearing.South, (-3, -8)))
}

test(
"Where R = Turn Right, L = Turn Left and A = Advance, the robot can follow a series of instructions and end up with the correct position and direction - instructions to move east and north") {
pending
Robot(Bearing.South, (8, 4)).simulate("LAAARRRALLLL") should be(
Robot(Bearing.North, (11, 5)))
}
}
import Bearing.{East, North, South, West}

case class Robot(bearing: Bearing, tuple: (Int, Int)) {

def simulate(sim: String): Robot =
sim.foldLeft(this) { (acc, op) =>
op match {
case 'L' => acc.turnLeft
case 'R' => acc.turnRight
}
}

def turnRight(): Robot = Robot(bearing match {
case North => East
case East => South
case South => West
case West => North
}, coordinates)

def turnLeft(): Robot = Robot(bearing match {
case North => West
case East => North
case South => East
case West => South
}, coordinates)

def advance: Robot = bearing match {
case Bearing.North => new Robot(bearing, (coordinates._1,  coordinates._2 + 1))
case Bearing.East => new Robot(bearing, (coordinates._1 + 1,  coordinates._2))
case Bearing.South => new Robot(bearing, (coordinates._1,  coordinates._2 - 1))
case Bearing.West => new Robot(bearing, (coordinates._1 - 1,  coordinates._2 ))
}

def coordinates() = tuple

}

sealed class Bearing

object Bearing {

case object North extends Bearing

case object South extends Bearing

case object East extends Bearing

case object West extends Bearing

}