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

Advent of Code 2022 - Day 13

2022/day13.livemd

Advent of Code 2022 - Day 13

Mix.install([
  :kino,
  {:kino_aoc, git: "https://github.com/ljgago/kino_aoc"},
  :kino_vega_lite
])

Input

test_input = """
[1,1,3,1,1]
[1,1,5,1,1]

[[1],[2,3,4]]
[[1],4]

[9]
[[8,7,6]]

[[4,4],4,4]
[[4,4],4,4,4]

[7,7,7,7]
[7,7,7]

[]
[3]

[[[]]]
[[]]

[1,[2,[3,[4,[5,6,7]]]],8,9]
[1,[2,[3,[4,[5,6,0]]]],8,9]
"""
{:ok, puzzle_input} = KinoAOC.download_puzzle("2022", "13", System.fetch_env!("LB_AOC_SESSION"))
input_field =
  Kino.Input.select("input", [
    {test_input, "test_input"},
    {puzzle_input, "puzzle_input"}
  ])

Parse & Prep

parsed =
  input_field
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(&Jason.decode!/1)
defmodule Decoder do
  def compare([], []), do: :eq
  def compare([_ | _], []), do: :gt
  def compare([], [_ | _]), do: :lt

  def compare([a | resta], [b | restb]) do
    case compare(a, b) do
      :eq -> compare(resta, restb)
      other -> other
    end
  end

  def compare(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a < b -> :lt
      a > b -> :gt
      true -> :eq
    end
  end

  def compare(a, b), do: compare(List.wrap(a), List.wrap(b))
end

Part 1

parsed
|> Enum.chunk_every(2)
|> Enum.map(fn [a, b] -> Decoder.compare(a, b) end)
|> Enum.with_index(1)
|> Enum.filter(&amp;(elem(&amp;1, 0) == :lt))
|> Enum.map(&amp;elem(&amp;1, 1))
|> Enum.sum()

Part 2

sorted =
  [[[2]], [[6]] | parsed]
  |> Enum.sort(Decoder)

divider_packet_1 = Enum.find_index(sorted, &amp;(&amp;1 == [[2]])) + 1
divider_packet_2 = Enum.find_index(sorted, &amp;(&amp;1 == [[6]])) + 1
divider_packet_1 * divider_packet_2