Current section
Files
Jump to
Current section
Files
lib/instructions_interpreter.ex
defmodule MarsExplorer.InstructionsInterpreter do
@moduledoc """
Module responsible for interpreting the exploration instructions
"""
@grid_regex ~r/\A(\d) (\d)\z/
@place_regex ~r/\A(\d) (\d) (N|E|S|W)\z/
@movements_regex ~r/^(L|M|R)+$/
@directions %{
"N" => :north,
"E" => :east,
"W" => :west,
"S" => :south
}
@doc """
Interprets instructions from a instructions list.
## Examples
iex> alias MarsExplorer.InstructionsInterpreter
MarsExplorer.InstructionsInterpreter
iex> instructions = ["5 5", "1 2 N", "LMLMLMLMM", "3 3 E", "MMRMMRMRRM"]
["5 5", "1 2 N", "LMLMLMLMM", "3 3 E", "MMRMMRMRRM"]
iex> instructions |> InstructionsInterpreter.interpret()
[
{:grid, %{north: 5, east: 5}},
{:place, %{north: 2, east: 1, direction: :north}},
[
:turn_left,
:move,
:turn_left,
:move,
:turn_left,
:move,
:turn_left,
:move,
:move
],
{:place, %{north: 3, east: 3, direction: :east}},
[
:move,
:move,
:turn_right,
:move,
:move,
:turn_right,
:move,
:turn_right,
:turn_right,
:move
]
]
"""
def interpret(instructions) do
instructions
|> Enum.map(&classify_instruction/1)
|> Enum.map(&do_interpret/1)
end
defp classify_instruction(instruction) do
%{
grid: String.match?(instruction, @grid_regex),
place: String.match?(instruction, @place_regex),
movements: String.match?(instruction, @movements_regex),
instruction: instruction
}
end
defp do_interpret(%{grid: true, instruction: instruction}) do
to_integer = &String.to_integer/1
[_command, east, north] = Regex.run(@grid_regex, instruction)
{:grid, %{east: to_integer.(east), north: to_integer.(north)}}
end
defp do_interpret(%{place: true, instruction: instruction}) do
to_integer = &String.to_integer/1
[_command, east, north, direction] = Regex.run(@place_regex, instruction)
{:place,
%{east: to_integer.(east), north: to_integer.(north), direction: @directions[direction]}}
end
defp do_interpret(%{movements: true, instruction: instruction}) do
instruction
|> String.graphemes()
|> Enum.map(&movement/1)
end
defp do_interpret(%{instruction: instruction}), do: {:invalid, instruction}
defp movement("L"), do: :turn_left
defp movement("R"), do: :turn_right
defp movement("M"), do: :move
end