defmodule MarsExplorer.Probe do @moduledoc """ Module responsible for executing probe actions """ defstruct north: 0, east: 0, direction: :north @type t :: %__MODULE__{ north: integer(), east: integer(), direction: :west | :north | :east | :south } @doc """ Moves the probe forward ## Examples iex> alias MarsExplorer.Probe MarsExplorer.Probe iex> probe = %Probe{north: 0, direction: :north} %Probe{north: 0, direction: :north} iex> probe |> Probe.move %Probe{north: 1} iex> probe |> Probe.move |> Probe.move %Probe{north: 2} """ @spec move(t()) :: t() def move(%__MODULE__{direction: direction} = probe) do case direction do :north -> probe |> move_north() :east -> probe |> move_east() :south -> probe |> move_south() :west -> probe |> move_west() end end defp move_east(%__MODULE__{} = probe), do: %__MODULE__{probe | east: probe.east + 1} defp move_west(%__MODULE__{} = probe), do: %__MODULE__{probe | east: probe.east - 1} defp move_north(%__MODULE__{} = probe), do: %__MODULE__{probe | north: probe.north + 1} defp move_south(%__MODULE__{} = probe), do: %__MODULE__{probe | north: probe.north - 1} @doc """ Turns the probe left ## Examples iex> alias MarsExplorer.Probe MarsExplorer.Probe iex> probe = %Probe{direction: :north} %Probe{direction: :north} iex> probe |> Probe.turn_left %Probe{direction: :west} """ @spec move(t()) :: t() def turn_left(%__MODULE__{direction: direction} = probe) do new_direction = case direction do :north -> :west :east -> :north :west -> :south :south -> :east end %__MODULE__{probe | direction: new_direction} end @doc """ Turns the probe right ## Examples iex> alias MarsExplorer.Probe MarsExplorer.Probe iex> probe = %Probe{direction: :north} %Probe{direction: :north} iex> probe |> Probe.turn_right %Probe{direction: :east} """ @spec move(t()) :: t() def turn_right(%__MODULE__{direction: direction} = probe) do new_direction = case direction do :north -> :east :east -> :south :west -> :north :south -> :west end %__MODULE__{probe | direction: new_direction} end end