aoc/22/lib/days/day13.ex
2023-12-04 10:25:33 +01:00

67 lines
1.5 KiB
Elixir

defmodule AOC.Day13 do
use AOC.Day, day: 13
alias AOC.Day13.Packet
defmodule Packet do
def compare({p1, p2}) do
compare(p1, p2)
end
def compare([], []), do: :eq
def compare([], _l), do: :lt
def compare(_l, []), do: :gt
def compare(x, l) when is_number(x) and is_list(l), do: compare([x], l)
def compare(l, x) when is_number(x) and is_list(l), do: compare(l, [x])
def compare([h1 | tl1], [h2 | tl2]) do
case compare(h1, h2) do
:eq -> compare(tl1, tl2)
x -> x
end
end
def compare(x, y) when x < y, do: :lt
def compare(x, y) when x == y, do: :eq
def compare(x, y) when x > y, do: :gt
end
def parse_input(lines) do
lines
|> Enum.chunk_by(&(&1 == ""))
|> Enum.reject(&(&1 == [""]))
|> Enum.map(fn [p1, p2] ->
{parse_packet(p1), parse_packet(p2)}
end)
end
def parse_packet(packet) do
packet
|> String.to_charlist()
|> Code.string_to_quoted()
|> elem(1)
end
def part1(pairs) do
pairs
|> Enum.map(&Packet.compare/1)
|> Enum.with_index()
|> Enum.filter(&(elem(&1, 0) == :lt))
|> Enum.map(&elem(&1, 1))
|> Enum.map(&Kernel.+(&1, 1))
|> Enum.sum()
end
@divider_packets [[[2]], [[6]]]
def part2(pairs) do
pairs
|> Enum.flat_map(fn {p1, p2} -> [p1, p2] end)
|> Kernel.++(@divider_packets)
|> Enum.sort(Packet)
|> Enum.with_index()
|> Enum.filter(&(elem(&1, 0) in @divider_packets))
|> Enum.map(&elem(&1, 1))
|> Enum.map(&Kernel.+(&1, 1))
|> Enum.reduce(&Kernel.*/2)
end
end