Avatar of JaeHyoLee

JaeHyoLee's solution

to Robot Simulator in the Lua Track

Published at Jul 13 2018 · 1 comment
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
  • advance

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
    • Advance twice
    • Turn left
    • Advance once
    • 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.

Running the tests

To run the tests, run the command busted from within the exercise directory.

Further information

For more detailed information about the Lua track, including how to get help if you're having trouble, please visit the exercism.io Lua language 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.

robot-simulator_spec.lua

local Robot = require('robot-simulator')

describe('robot-simulator', function()
  it('should make the current x, y, and heading available', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    assert.equal(5, robot.x)
    assert.equal(10, robot.y)
    assert.equal('north', robot.heading)
  end)

  it('should move forward when an A command is given', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    robot:move('A')
    assert.equal(5, robot.x)
    assert.equal(11, robot.y)
    assert.equal('north', robot.heading)
  end)

  it('should change heading clockwise when an R command is given', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    robot:move('R')
    assert.equal(5, robot.x)
    assert.equal(10, robot.y)
    assert.equal('east', robot.heading)
  end)

  it('should change heading counter-clockwise when an L command is given', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    robot:move('L')
    assert.equal(5, robot.x)
    assert.equal(10, robot.y)
    assert.equal('west', robot.heading)
  end)

  it('should be able to chain commands', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    robot:move('LAR')
    assert.equal(4, robot.x)
    assert.equal(10, robot.y)
    assert.equal('north', robot.heading)
  end)

  it('should be able to turn all the way around by turning clockwise', function()
    local robot = Robot{ x = 7, y = -10, heading = 'north' }
    robot:move('RRRR')
    assert.equal(7, robot.x)
    assert.equal(-10, robot.y)
    assert.equal('north', robot.heading)
  end)

  it('should be able to turn all the way around by turning counter-clockwise', function()
    local robot = Robot{ x = 5, y = 10, heading = 'south' }
    robot:move('LLLL')
    assert.equal(5, robot.x)
    assert.equal(10, robot.y)
    assert.equal('south', robot.heading)
  end)

  it('should be able to advance in all directions', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    robot:move('ARAARAARAR')
    assert.equal(6, robot.x)
    assert.equal(9, robot.y)
    assert.equal('north', robot.heading)
  end)

  it('should raise an error when an invalid command is used', function()
    local robot = Robot{ x = 5, y = 10, heading = 'north' }
    assert.has_errors(function() robot:move('ARALZR') end)
  end)
end)
local robot = {}
local brain = { 
  north = { L = 'west', R = 'east', y = 1 }, 
  east = { L = 'north', R = 'south', x = 1 },
  south = { L = 'east', R = 'west', y = -1 },
  west = { L = 'south', R = 'north', x = -1 }
  }

local function move(self, command)
  for i = 1, #command do
    local c = command:sub(i,i)
    if c == 'R' or c == 'L' then self.heading = brain[self.heading][c] 
    elseif c == 'A' then 
      self.x = self.x + (brain[self.heading].x or 0)
      self.y = self.y + (brain[self.heading].y or 0)
    else
      assert(false, 'unknown command')
    end
  end
end

return function(p)
  return {
    x = p.x,
    y = p.y,
    heading = p.heading,
    move = move
  }
end

Community comments

Find this solution interesting? Ask the author a question to learn more.
Avatar of ryanplusplus

Looks good. Now you just need to remove local robot = {} :)

What can you learn from this solution?

A huge amount can be learned from reading other people’s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

  • What compromises have been made?
  • Are there new concepts here that you could read more about to improve your understanding?