Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

AoC 2022 - day 13

tradfursten-elixir/day_13.livemd

AoC 2022 - day 13

Mix.install([:kino])

Section

input = Kino.Input.textarea("input")
defmodule Day13 do
  def solve1(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.chunk_every(2)
    |> Enum.map(fn [a, b] ->
      {a, _} = Code.eval_string(a)
      {b, _} = Code.eval_string(b)
      {a, b}
    end)
    |> Enum.map(fn {a, b} ->
      compare(a, b)
      # PacketComparator.compare(a, b)
    end)
    |> Enum.with_index()
    |> Enum.filter(fn {a, _} -> a end)
    |> Enum.map(fn {_, i} -> i + 1 end)
    |> Enum.sum()
  end

  def solve2(input) do
    packages =
      input
      |> String.split("\n", trim: true)
      |> Enum.map(fn a ->
        {a, _} = Code.eval_string(a)
        a
      end)

    divider_one = [[2]]
    divider_two = [[6]]

    packages =
      [divider_one | [divider_two | packages]]
      |> Enum.reduce([], fn a, acc ->
        {less, greater} = acc |> Enum.split_while(fn x -> compare(x, a) end)
        less ++ [a] ++ greater
      end)

    index_one = Enum.find_index(packages, fn a -> a == divider_one end) + 1
    index_two = Enum.find_index(packages, fn a -> a == divider_two end) + 1
    index_one * index_two
  end

  defp compare([a | at], [a | bt]), do: compare(at, bt)
  defp compare([], _), do: true
  defp compare(_, []), do: false

  defp compare([a | at], [b | bt]) do
    case compare_item(a, b) do
      :continue -> compare(at, bt)
      valid -> valid
    end
  end

  defp compare_item([], _), do: true
  defp compare_item(_, []), do: false

  defp compare_item(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a < b -> true
      a == b -> :continue
      b < a -> false
    end
  end

  defp compare_item(a, b) when is_list(a) and is_integer(b) do
    compare(a, [b])
  end

  defp compare_item(a, b) when is_integer(a) and is_list(b) do
    compare([a], b)
  end

  defp compare_item(a, b), do: compare(a, b)
end
Kino.Input.read(input) |> Day13.solve1()
Kino.Input.read(input) |> Day13.solve2()