93 lines
2.5 KiB
Elixir
93 lines
2.5 KiB
Elixir
defmodule AOC.Day12 do
|
|
@turn_right %{
|
|
N: :E,
|
|
E: :S,
|
|
S: :W,
|
|
W: :N
|
|
}
|
|
|
|
def parse_input do
|
|
AOC.Util.input_lines(12, 1)
|
|
|> Enum.map(fn line ->
|
|
{action, value} = String.split_at(line, 1)
|
|
action = String.to_atom(action)
|
|
value = String.to_integer(value)
|
|
|
|
{action, value}
|
|
end)
|
|
end
|
|
|
|
def handle_instruction1({:N, value}, acc), do: Map.update!(acc, :y, &(&1 - value))
|
|
def handle_instruction1({:E, value}, acc), do: Map.update!(acc, :x, &(&1 + value))
|
|
def handle_instruction1({:S, value}, acc), do: Map.update!(acc, :y, &(&1 + value))
|
|
def handle_instruction1({:W, value}, acc), do: Map.update!(acc, :x, &(&1 - value))
|
|
|
|
def handle_instruction1({:F, value}, %{dir: dir} = acc),
|
|
do: handle_instruction1({dir, value}, acc)
|
|
|
|
def handle_instruction1({:L, value}, acc), do: handle_instruction1({:R, -value}, acc)
|
|
|
|
def handle_instruction1({:R, value}, %{dir: dir} = acc) do
|
|
value = rem(div(value, 90), 4)
|
|
|
|
value =
|
|
if value < 0 do
|
|
value + 4
|
|
else
|
|
value
|
|
end
|
|
|
|
dir =
|
|
List.duplicate(nil, value)
|
|
|> Enum.reduce(dir, fn _, d -> Map.get(@turn_right, d) end)
|
|
|
|
Map.put(acc, :dir, dir)
|
|
end
|
|
|
|
def handle_instruction2({:N, value}, acc), do: Map.update!(acc, :wpy, &(&1 - value))
|
|
def handle_instruction2({:E, value}, acc), do: Map.update!(acc, :wpx, &(&1 + value))
|
|
def handle_instruction2({:S, value}, acc), do: Map.update!(acc, :wpy, &(&1 + value))
|
|
def handle_instruction2({:W, value}, acc), do: Map.update!(acc, :wpx, &(&1 - value))
|
|
|
|
def handle_instruction2({:F, value}, %{x: x, y: y, wpx: wpx, wpy: wpy} = acc),
|
|
do: %{acc | x: x + value * wpx, y: y + value * wpy}
|
|
|
|
def handle_instruction2({:L, value}, acc), do: handle_instruction2({:R, -value}, acc)
|
|
|
|
def handle_instruction2({:R, value}, %{wpx: wpx, wpy: wpy} = acc) do
|
|
value = rem(div(value, 90), 4)
|
|
|
|
value =
|
|
if value < 0 do
|
|
value + 4
|
|
else
|
|
value
|
|
end
|
|
|
|
{wpx, wpy} =
|
|
case value do
|
|
0 -> {wpx, wpy}
|
|
1 -> {-wpy, wpx}
|
|
2 -> {-wpx, -wpy}
|
|
3 -> {wpy, -wpx}
|
|
end
|
|
|
|
%{acc | wpx: wpx, wpy: wpy}
|
|
end
|
|
|
|
def handle_instructions(instructions, instruction_handler) do
|
|
acc = %{x: 0, y: 0, dir: :E, wpx: 10, wpy: -1}
|
|
Enum.reduce(instructions, acc, instruction_handler)
|
|
end
|
|
|
|
def parts do
|
|
input = parse_input()
|
|
%{x: x, y: y} = handle_instructions(input, &handle_instruction1/2)
|
|
part1 = abs(x) + abs(y)
|
|
|
|
%{x: x, y: y} = handle_instructions(input, &handle_instruction2/2)
|
|
part2 = abs(x) + abs(y)
|
|
|
|
{part1, part2}
|
|
end
|
|
end
|