Skip to content

Instantly share code, notes, and snippets.

@nikolasrangel
Created October 2, 2020 01:03
Show Gist options
  • Save nikolasrangel/89684043d1c33afe6646376415310ba3 to your computer and use it in GitHub Desktop.
Save nikolasrangel/89684043d1c33afe6646376415310ba3 to your computer and use it in GitHub Desktop.
defmodule RobotSimulator do
@doc """
Create a Robot Simulator given an initial direction and position.
Valid directions are: `:north`, `:east`, `:south`, `:west`
"""
@valid_directions [:north, :south, :east, :west]
@spec create() :: {:north, {0,0}}
def create(), do: {:north, {0,0}}
@spec create(direction :: atom, position :: {integer, integer}) :: any
def create(direction, {x, y} = position)
when direction in @valid_directions and is_number(x) and is_number(y),
do: {direction, position}
def create(direction, _position)
when direction in @valid_directions,
do: {:error, "invalid position"}
# def create(direction, _position)
# when direction in @valid_directions,
# do: {:error, "invalid position"}
def create(_direction, _position), do: {:error, "invalid direction"}
@doc """
Simulate the robot's movement given a string of instructions.
Valid instructions are: "R" (turn right), "L", (turn left), and "A" (advance)
"""
@spec simulate(robot :: any, instructions :: String.t()) :: any
def simulate(robot, "") do
robot
end
def simulate({:north, {x, y} = position}, instructions) do
{ command, rest } = String.split_at(instructions, 1)
case command do
"R" ->
simulate({:east, position}, rest)
"L" ->
simulate({:west, position}, rest)
"A" ->
simulate({:north, {x, y+1}}, rest)
_ ->
{:error, "invalid instruction"}
end
end
def simulate({:east, {x, y} = position}, instructions) do
{ command, rest } = String.split_at(instructions, 1)
case command do
"R" ->
simulate({:south, position}, rest)
"L" ->
simulate({:north, position}, rest)
"A" ->
simulate({:east, {x+1, y}}, rest)
_ ->
{:error, "invalid instruction"}
end
end
def simulate({:south, {x, y} = position}, instructions) do
{ command, rest } = String.split_at(instructions, 1)
case command do
"R" ->
simulate({:west, position}, rest)
"L" ->
simulate({:east, position}, rest)
"A" ->
simulate({:south, {x, y-1}}, rest)
_ ->
{:error, "invalid instruction"}
end
end
def simulate({:west, {x, y} = position}, instructions) do
{ command, rest } = String.split_at(instructions, 1)
case command do
"R" ->
simulate({:north, position}, rest)
"L" ->
simulate({:south, position}, rest)
"A" ->
simulate({:west, {x-1, y}}, rest)
_ ->
{:error, "invalid instruction"}
end
end
@doc """
Return the robot's direction.
Valid directions are: `:north`, `:east`, `:south`, `:west`
"""
@spec direction(robot :: any) :: atom
def direction({ direction, _ }) do
direction
end
@doc """
Return the robot's position.
"""
@spec position(robot :: any) :: {integer, integer}
def position({ _, position }) do
position
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment