Day 09
Section
defmodule Day09 do
def part1(input) do
input
|> Enum.reduce({List.duplicate({0, 0}, 2), [{0, 0}]}, fn instruction, {knots, acc} ->
move(instruction, knots, acc)
end)
|> elem(1)
|> Enum.uniq()
|> length()
end
def part2(input) do
input
|> Enum.reduce({List.duplicate({0, 0}, 10), [{0, 0}]}, fn instruction, {knots, acc} ->
move(instruction, knots, acc)
end)
|> elem(1)
|> Enum.uniq()
|> length()
end
defp move({_, 0}, rope, acc), do: {rope, acc}
defp move({direction, dist}, [h | t], acc) do
h = move_once(h, direction)
rev_rope =
for knot <- t, reduce: [h] do
[prev | _] = state -> [follow(knot, prev) | state]
end
move({direction, dist - 1}, Enum.reverse(rev_rope), [hd(rev_rope) | acc])
end
defp move_once({x, y}, "U"), do: {x, y + 1}
defp move_once({x, y}, "D"), do: {x, y - 1}
defp move_once({x, y}, "L"), do: {x - 1, y}
defp move_once({x, y}, "R"), do: {x + 1, y}
defp follow({xt, yt}, {xh, yh}) when abs(xt - xh) <= 1 and abs(yt - yh) <= 1 do
{xt, yt}
end
defp follow({xt, yt}, {xh, yh}) do
{xt - sign(xt - xh), yt - sign(yt - yh)}
end
defp sign(0), do: 0
defp sign(n), do: n |> abs() |> div(n)
end
input =
"#{__DIR__}/day09.txt"
|> File.stream!()
|> Stream.map(&String.trim/1)
|> Stream.map(&String.split/1)
|> Stream.map(fn [direction, distance] -> {direction, String.to_integer(distance)} end)
Day09.part1(input)
Day09.part2(input)