68 lines
1.5 KiB
Elixir
68 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
|