-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathday_09.ex
More file actions
71 lines (58 loc) · 1.8 KB
/
day_09.ex
File metadata and controls
71 lines (58 loc) · 1.8 KB
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
59
60
61
62
63
64
65
66
67
68
69
70
71
defmodule AdventOfCode.Y2022.Day09 do
@moduledoc """
--- Day 9: Rope Bridge ---
Problem Link: https://adventofcode.com/2022/day/9
Difficulty: m
Tags: grid walk
"""
alias AdventOfCode.Helpers.{InputReader, Transformers}
def input, do: InputReader.read_from_file(2022, 9)
def run(input \\ input()) do
instructions = parse(input)
{part1(instructions), part2(instructions)}
end
defp part1(instructions), do: solve(instructions, 2)
defp part2(instructions), do: solve(instructions, 10)
defp solve(instructions, count) do
start_rope = List.duplicate({0, 0}, count)
{_rope, visited} =
Enum.reduce(instructions, {start_rope, MapSet.new([{0, 0}])}, fn {dir, steps}, acc ->
Enum.reduce(1..steps, acc, fn _, {rope, visited} ->
[head | tails] = rope
new_head = move_head(head, dir)
# Each knot follows the one before it
new_rope =
Enum.scan(tails, new_head, fn tail, prev ->
follow(prev, tail)
end)
full_rope = [new_head | new_rope]
{full_rope, MapSet.put(visited, List.last(full_rope))}
end)
end)
MapSet.size(visited)
end
defp parse(input) do
input
|> Transformers.lines()
|> Enum.map(fn line ->
[dir, steps] = String.split(line, " ")
{dir, String.to_integer(steps)}
end)
end
defp move_head({r, c}, "U"), do: {r - 1, c}
defp move_head({r, c}, "D"), do: {r + 1, c}
defp move_head({r, c}, "L"), do: {r, c - 1}
defp move_head({r, c}, "R"), do: {r, c + 1}
defp follow({hr, hc}, {tr, tc}) do
dr = hr - tr
dc = hc - tc
if abs(dr) <= 1 and abs(dc) <= 1 do
{tr, tc}
else
{tr + sign(dr), tc + sign(dc)}
end
end
defp sign(0), do: 0
defp sign(n) when n > 0, do: 1
defp sign(n) when n < 0, do: -1
end