Powered by AppSignal & Oban Pro

🎄 Year 2022 🔔 Day 13

elixir/notebooks/2022/day13.livemd

🎄 Year 2022 🔔 Day 13

Parse input

filename = "#{__DIR__}/../../../inputs/2022/day13.txt"

signals =
  File.stream!(filename)
  |> Enum.map(&String.trim/1)
  |> Enum.chunk_every(2, 3)
  |> Enum.map(
    &Enum.map(&1, fn string ->
      {parsed, []} = Code.eval_string(string)
      parsed
    end)
  )

Shared Code

defmodule Helper do
  def compare([], []), do: :inconclusive
  def compare([], [_ | _]), do: true
  def compare([_ | _], []), do: false

  def compare([a | atail], [b | btail]) when is_integer(a) and is_integer(b) do
    cond do
      a == b -> compare(atail, btail)
      a < b -> true
      true -> false
    end
  end

  def compare([a | atail], [b | btail]) do
    a = if is_list(a), do: a, else: [a]
    b = if is_list(b), do: b, else: [b]

    case compare(a, b) do
      :inconclusive -> compare(atail, btail)
      result -> result
    end
  end
end

Part One

signals
|> Enum.map(fn [left, right] -> Helper.compare(left, right) end)
|> Enum.with_index(1)
|> Enum.filter(&elem(&1, 0))
|> Enum.map(&elem(&1, 1))
|> Enum.sum()

Part two

Enum.sort_by(1..100, &(rem(&1, 2) == 0), :desc)
divider_packets = [[[2]], [[6]]]

signals
|> Enum.concat([divider_packets])
|> Enum.concat()
|> Enum.sort(fn left, right -> Helper.compare(left, right) end)
|> Enum.with_index(1)
|> Enum.filter(fn {packet, i} -> Enum.any?(divider_packets, &(&1 == packet)) end)
|> Enum.map(&elem(&1, 1))
|> Enum.product()