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