Rain Risk
defmodule Aoc2020.Day12 do
@moduledoc "Rain Risk"
def run() do
parse_input()
|> follow_instructions({0, 0, :east})
|> (fn {x, y, _} -> abs(x) + abs(y) end).()
end
def parse_input() do
# test_input()
File.read!("priv/inputs/2020/day12.txt")
|> String.trim()
|> String.split("\n")
|> Enum.map(fn line ->
{action, value} = String.split_at(line, 1)
{action_name(action), String.to_integer(value)}
end)
end
def action_name(letter) do
Map.fetch!(
%{
"N" => :north,
"S" => :south,
"E" => :east,
"W" => :west,
"R" => :right,
"L" => :left,
"F" => :forward
},
letter
)
end
def test_input do
"F10\nN3\nF7\nR90\nF11"
end
def follow_instructions(instructions, from) do
Enum.reduce(instructions, from, fn instruction, location -> step(location, instruction) end)
end
def step({x, y, facing}, {:north, dist}), do: {x, y - dist, facing}
def step({x, y, facing}, {:south, dist}), do: {x, y + dist, facing}
def step({x, y, facing}, {:east, dist}), do: {x + dist, y, facing}
def step({x, y, facing}, {:west, dist}), do: {x - dist, y, facing}
def step({x, y, facing}, {:right, degress}), do: {x, y, compass_direction(facing, degress)}
def step({x, y, facing}, {:left, degress}), do: {x, y, compass_direction(facing, 0 - degress)}
def step({x, y, facing}, {:forward, dist}), do: step({x, y, facing}, {facing, dist})
def compass_direction(current, turn_degrees) do
compass = %{0 => :north, 90 => :east, 180 => :south, 270 => :west}
current_degrees = elem(Enum.find(compass, fn {_, v} -> v == current end), 0)
t2 = rem(current_degrees + turn_degrees, 360)
case t2 >= 0 do
true -> Map.fetch!(compass, t2)
false -> Map.fetch!(compass, 360 + t2)
end
end
end