-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathday_12.ex
58 lines (46 loc) · 2.55 KB
/
day_12.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
defmodule AdventOfCode.Y2020.Day12 do
@moduledoc """
--- Day 12: Rain Risk ---
Problem Link: https://adventofcode.com/2020/day/12
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2020, 12)
def run(input \\ input()) do
input = input |> Transformers.lines() |> parse_actions()
{distance(go(input)), distance(waypoints(input))}
end
defp parse_actions([]), do: []
defp parse_actions([<<dir::utf8>> <> val | xs]),
do: [{String.to_existing_atom(<<dir>>), String.to_integer(val)} | parse_actions(xs)]
defp go(dirs), do: go(dirs, {0, 0}, :E)
defp go([], pos, _), do: pos
defp go([{:N, val} | xs], {x, y}, f), do: go(xs, {x, y + val}, f)
defp go([{:S, val} | xs], {x, y}, f), do: go(xs, {x, y - val}, f)
defp go([{:E, val} | xs], {x, y}, f), do: go(xs, {x + val, y}, f)
defp go([{:W, val} | xs], {x, y}, f), do: go(xs, {x - val, y}, f)
defp go([{:F, val} | xs], {x, y}, f), do: go([{f, val} | xs], {x, y}, f)
defp go([{lr, val} | xs], {x, y}, f),
do: go([{turn(f, lr, val), 0} | xs], {x, y}, turn(f, lr, val))
defp turn(:N, :L, val), do: do_turn([:W, :S, :E], val)
defp turn(:N, :R, val), do: do_turn([:E, :S, :W], val)
defp turn(:S, :L, val), do: do_turn([:E, :N, :W], val)
defp turn(:S, :R, val), do: do_turn([:W, :N, :E], val)
defp turn(:E, :L, val), do: do_turn([:N, :W, :S], val)
defp turn(:E, :R, val), do: do_turn([:S, :W, :N], val)
defp turn(:W, :L, val), do: do_turn([:S, :E, :N], val)
defp turn(:W, :R, val), do: do_turn([:N, :E, :S], val)
defp do_turn(directions, val), do: Enum.at(directions, div(val, 90) - 1)
defp distance({x, y}), do: abs(x) + abs(y)
defp waypoints(data), do: waypoints(data, [{0, 0}, {10, 1}])
defp waypoints([], [ship, _]), do: ship
defp waypoints([rule | xs], positions), do: waypoints(xs, positions(rule, positions))
defp positions({:N, val}, [{x, y}, {wx, wy}]), do: [{x, y}, {wx, wy + val}]
defp positions({:S, val}, [{x, y}, {wx, wy}]), do: [{x, y}, {wx, wy - val}]
defp positions({:E, val}, [{x, y}, {wx, wy}]), do: [{x, y}, {wx + val, wy}]
defp positions({:W, val}, [{x, y}, {wx, wy}]), do: [{x, y}, {wx - val, wy}]
defp positions({:F, val}, [{x, y}, {wx, wy}]), do: [{x + wx * val, y + wy * val}, {wx, wy}]
defp positions({lr, val}, [{x, y}, {wx, wy}]), do: [{x, y}, turn_waypoint({wx, wy}, lr, val)]
defp turn_waypoint({wx, wy}, _, 0), do: {wx, wy}
defp turn_waypoint({wx, wy}, :L, val), do: turn_waypoint({-wy, wx}, :L, val - 90)
defp turn_waypoint({wx, wy}, :R, val), do: turn_waypoint({wy, -wx}, :R, val - 90)
end