Untitled notebook
Section
defmodule Day9 do
def parse_input(input) do
input
|> String.split("\n", trim: true)
|> Enum.flat_map(fn
<> ->
steps = String.to_integer(String.trim(steps))
List.duplicate(x, steps)
end)
end
def part_1(input) do
instructions = parse_input(input)
{_, _, history} =
for dir <- instructions, reduce: {{0, 0}, {0, 0}, [{0, 0}]} do
{hpos, {tx, ty} = tpos, history} ->
hpos_next = move_head(hpos, dir)
tpos = move_tail(hpos_next, tpos)
{hpos_next, tpos, [tpos | history]}
end
history
|> MapSet.new()
|> MapSet.size()
end
def part_2(input) do
instructions = parse_input(input)
{_, _, history} =
for dir <- instructions,
reduce: {{0, 0}, List.duplicate({0, 0}, 9), MapSet.new([{0, 0}])} do
{hpos, tpos, history} ->
hpos_next = move_head(hpos, dir)
{tpos, _} =
Enum.map_reduce(tpos, {hpos, hpos_next}, fn tpos_prev, {hpos, hpos_next} ->
tpos = move_tail(hpos_next, tpos_prev)
{tpos, {tpos_prev, tpos}}
end)
{hpos_next, tpos, MapSet.put(history, List.last(tpos))}
end
MapSet.size(history)
end
def move_head({hx, hy}, "U"), do: {hx + 1, hy}
def move_head({hx, hy}, "D"), do: {hx - 1, hy}
def move_head({hx, hy}, "R"), do: {hx, hy + 1}
def move_head({hx, hy}, "L"), do: {hx, hy - 1}
def move_tail({hx, hy} = hpos_next, {tx, ty} = tpos) do
head_too_far = :math.sqrt((hx - tx) ** 2 + (hy - ty) ** 2) >= 2
if head_too_far do
xinc = sign(hx - tx)
yinc = sign(hy - ty)
{tx + xinc, ty + yinc}
else
tpos
end
end
defp sign(x) when x > 0, do: 1
defp sign(x) when x == 0, do: 0
defp sign(x) when x < 0, do: -1
end
test_input = """
R 4
U 4
L 3
D 1
R 4
D 1
L 5
R 2
"""
Day9.part_1(test_input)
input = File.read!("day9_input.txt")
Day9.part_1(input)
test_input_part_2 = """
R 5
U 8
L 8
D 3
R 17
D 10
L 25
U 20
"""
Day9.part_2(test_input_part_2)
Day9.part_2(input)