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

Day13

day13.livemd

Day13

Mix.install([
  {:kino, "~> 0.8.0"},
  :poison
])
:ok

Section

input = Kino.Input.textarea("Puzzle input")

List Parser

defmodule ListParser do
  def parse(line) do
    line
    |> do_parse()
  end

  defp do_parse(str, acc \\ [])

  defp do_parse("", acc), do: acc

  defp do_parse("]" <> rest, acc) do
    {rest, acc}
  end

  defp do_parse("[" <> rest, acc) do
    {rest, value} = do_parse(rest)

    do_parse(rest, acc ++ [value])
  end

  defp do_parse("," <> rest, acc) do
    do_parse(rest, acc)
  end

  defp do_parse(rest, acc) do
    {v, rest} = Integer.parse(rest)
    # {rest, v} = take_number(rest, "")

    do_parse(rest, acc ++ [v])
  end
end
{:module, ListParser, <<70, 79, 82, 49, 0, 0, 9, ...>>, {:do_parse, 2}}

Pair Comparer

defmodule PairComparer do
  def compare([], []), do: :eq

  def compare([], _), do: :lt

  def compare(_, []), do: :gt

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

  def compare([left | left_rest], [right | right_rest]) do
    case compare(left, right) do
      :eq -> compare(left_rest, right_rest)
      res -> res
    end
  end

  def compare(left, right) when is_list(left), do: compare(left, [right])

  def compare(left, right) when is_list(right), do: compare([left], right)
end
{:module, PairComparer, <<70, 79, 82, 49, 0, 0, 8, ...>>, {:compare, 2}}

Read input and parse lists

input =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.map(&amp;ListParser.parse/1)
[
  [[[8, 6, [], 2], '\a', [8, 0, [7, 0], [[5, 6], 10, '\n']], [3, 8, [], ['\b\t', 4]], []]],
  [[[3, [2, [9, 4, 4], 1], [[3], [], [7, 10, 6, 6], [8, 6]]], [[8, 5], [2, [], '\a']]]],
  [[[[2, [5], '\n\n']], [2]]],
  [
    [
      '\a\n',
      [6, [[2, 10, 7, 9, 5], 7, 7, 0], 2, [[5, 10]], [[9, 1], [], [5, 7, 6], [2], [3]]],
      [[[5, 0, 10], 2, 8, [5, 6, 2, 2, 10], '\t'], 5, 8, 6, []],
      [
        [[0], [2, 1, 2, 1, 0], [9, 0], [0], [1, 3, 10, 1]],
        [5, '\b', [], 8, [3, 8, 7, 3]],
        [6, [3], 7, [8, 2], []]
      ]
    ]
  ],
  [[[[[9, 6, 10, 5, 2], [0, 10, 6, 8]], 2, [[4, 9, 3], 4], [9, [], 0, [7, 6, 2], 7]], []]],
  [
    [
      [6, [5], [], '\t', [7, 4, [6], 10]],
      [[[6, 3, 6, 4]], 2, 6],
      [3, [[9, 0, 6], [8, 4, 6], 10], [3, 0, 5], []],
      [[2, [2, 5, 3, 7, 1], 5], ['\b', []]]
    ]
  ],
  [
    [
      [],
      [4, [], 0, [], 6],
      [[[5], [4, 3, 6]], [[7, 6], 5], [[3, 9], 2], 7],
      [4, [], 2, [3, [], 10]]
    ]
  ],
  [
    [
      [[0, 2], [6, [5, 9, 8], [1, 8, 1]]],
      [[[1, 3, 0], [], 0, 10], [6], 3],
      [[[1, 1, 6, 2, 1]], 9],
      [[[5, 0, 4], 5, [1, 2, 5, 10, 2]], [[7, 8, 4], 1]]
    ]
  ],
  [[[1], [10, [10, 4, [0]]], [[[7, 6], [2, 2, 0, 7], '\n']]]],
  [[[[10, [5, 8], [2, 10, 2], [], 7], [2], 1]]],
  [[[[4, 4, [7, 4, 5]], 1, [[3], 6, [6, 7]], 6]]],
  [[[4], [[], [0]], [[[10, 7, 2, 8], 4], 9, [], [[3, 5, 1], []]], [[5, []], [], [4, 2], 9, 1]]],
  [[[[], 8, 4], [[7, [5, 4, 8, 8], 4], 7], [6], [2, 0]]],
  [[[[1, 0, 7, [5, 3, 5], []], 8, ['\t\a', [], [], 9, 10], 0], [[], 1, 0, []]]],
  [[[6, [], [5, 3, 7]], '\a', [['\n', [5], 9], 7]]],
  [
    [
      [[[4, 3, 10, 8], 4, [3, 1, 7], [0, 8, 0, 5, 6]], [[]]],
      [],
      [[3, '\t'], [[7, 0, 6, 9, 7], 8, [1, 10, 3], 1], 0]
    ]
  ],
  [
    [
      [[9, [5, 1, 8], 8, [4, 2, 0, 4], 4], [4, 0], 2],
      [1, [2], 9],
      [[], 9, 5, [1], 9],
      [[3, 5], [[2, 9, 7, 9], [4, 9, 7, 9, 6], 0, [0, 4, 7]], 5, [4, 5, 5]],
      []
    ]
  ],
  [[[[[], []], 3, 0, 6]]],
  [
    [
      [10, 5, 4, 2],
      [6, [[9, 9, 3, 8, 0]], 5],
      [2, [0, 9, []]],
      [[], [1, 10, 4, [9, 4], []]],
      [[[5, 7, 9], [], [5, 10]], [5, 7]]
    ]
  ],
  [[[], [10, 6, 9, 9, 0]]],
  [[[], [7, [[6, 0, 6, 7]], 8, [4, [3], [5, 8], 5], 10]]],
  [
    [
      [[8, [4], [9, 0, 1, 0, 3], 9, [5, 1, 10]], 3],
      [[1, 5, 4, 4], [[0, 6, 2, 2], 2, 3, [0, 3, 6]], 0, [[0, 6], 3, 10]],
      [10, 10, 0, 8, [[0], [5, 9, 5, 1], [10, 0, 10, 9]]],
      [5, 2]
    ]
  ],
  [
    [
      [[[7, 0], [6, 0, 2, 8, 7], 0], 5, ['\a', [6, 0, 5]]],
      [2, [[6, 5, 1, 10], [2, 0]], 0],
      [['\b', 9, '\t\n\a', [0]]]
    ]
  ],
  [
    [
      [[[7, 10, 2], 10, 10, [1, 2], [5, 7, 2]], [7, 3, [9, 4, 5, 10, 5], 7], 5, 9],
      [1, 1, [[4, 0, 10, 6], [3, 0], [2, 7, 2]]],
      [],
      [[4, 8, 0, 5, [5, 3, 5, 7, 0]], 6]
    ]
  ],
  [[[], []]],
  [
    [
      [[[1], 5, [1, 10, 1, 4, 1], '\t\b']],
      [4, [[0, 3, 0], [], [3, 5], [9, 1, 0], 2]],
      [[5, 1, 8, 9, [5, 6]], [6, 2, 5, 8, [1]]],
      []
    ]
  ],
  [[[10, 9, 0, [9, 5, 1, [5, 8, 9, 7]]], [4, [[], 7, 4]]]],
  [
    [
      [[1], 4, 4, [[], [2], 8, [6, 2, 6], []], 8],
      [[3, [], [1, 6, 6, 4, 9], [1, 2, 8, 4, 3]], [[], [0, 9, 9], [6, 5], [0, 6, 3, 3, 2], 3]],
      [[3], [5], 2],
      [[], 2, [[2, 3, 4, 6], [1, 7, 8, 10]]],
      [9, 3]
    ]
  ],
  [[[], [2, [5, 8, [2, 3, 5, 6, 0], [8, 4, 9, 7, 1]], [[8, 0], 9, 1, 2, [2, 5, 0]], 10]]],
  [[[8, [], 9, 6], [4, 2, 10, [], 9]]],
  [[[10, 8, '\t', 9, 8], [[], 0]]],
  [
    [
      [1, [9, 1, [6, 8]], 9, [[0], '\a', [0, 5, 5], [3, 5, 10, 7, 3], [1, 2, 9]], 8],
      [9, 4, 9, 9],
      [4, 3, [[2, 6, 7, 4, 7], [0, 5, 2], [2, 0, 2, 7, 6]], 4],
      [[[9, 2, 9, 4]], [5], [0, '\a']],
      [9, [[6], [3], [10, 0], 8, []], [], 1, 8]
    ]
  ],
  [
    [
      [[8, 4], 2, [[2], '\t', [5, 9, 3, 9], [5], [5, 5]], 2, 4],
      [8, 6, 3, 8],
      [1, ['\a', [2, 5, 9, 1], [2, 0], [8, 2, 4, 8]]],
      [1, 4],
      [8, 9, [7, 5, 4, [4, 10, 0, 8]], [1, '\n', 8], 8]
    ]
  ],
  [
    [
      [[[2, 2, 8, 10], 7, 0, 10], 7, 2],
      [5, 1, [4, 5], [3, 0, 5, [0], 1], [[2], [2, 7, 4, 7], 8, 9]],
      '\a\b\b\t',
      [[1, 0, 6, 4], [[1, 3, 0], 10, 1, 10, 0], 7, 9, 0],
      []
    ]
  ],
  [[[], [4, 6, [[1, 5, 8, 10], [], [7, 0, 3, 10]]], []]],
  [[[[], 4, 4], [7, [], 10, ['\b', 3, [8, 1, 5], [5, 4]]], [[], [[1, 4]], 2, [[], 7, 5], 3]]],
  [
    [
      [[[5, 7], 10, 9, [6, 0], [4, 9, 6, 7, 1]], []],
      [5, [[5]]],
      [[10, []]],
      [4, [[0], 3, [7, 0, 3], 9, 9]]
    ]
  ],
  [
    [
      [[], '\t', 9, 6],
      [],
      [2, 6, 5],
      [8, [8, [], [10, 3, ...], [9, ...]], 10],
      [[[1], [7, 5, 6, ...]], 7, [6, [], []]]
    ]
  ],
  [[[[[4, 3, 3], [], 1], [[], 5, 9, 0, 2], [[6], [5]], [0, 4, 0, 6], 10]]],
  [[[], [3, [[7, 1], '\b', '\n', [7, ...], '\a']]]],
  [
    [
      [[], [5], [1, 6, 1, 4, ...], 0],
      [5, [[6]], [[0, 3, ...], [3, ...]]],
      [[3], [[4, 2, ...], [5]], [], 2, 9],
      [6, 0]
    ]
  ],
  [[[], '\n']],
  [[[8, [], [[7, ...], [...]], 0], [['\n', [6, ...], 6], 5, 4, []]]],
  [[[3, 3, 1, '\b\n', ...], [10, 7, [...]], [0], [], []]],
  [['\b\n', [[[...], ...], [...], ...], [[...]]]],
  [[[3, [...], ...], [0, ...]]],
  [[[0], [...], ...]],
  [[[...]]],
  [[...]],
  [...],
  ...
]

Part 1

input
|> Enum.chunk_every(2)
|> Enum.with_index()
|> Enum.filter(fn {[a, b], _index} ->
  PairComparer.compare(a, b) == :lt
end)
|> Enum.map(fn {_, index} -> index + 1 end)
|> Enum.sum()
5625

Part 2

sorted =
  input
  |> Kernel.++([[[2]], [[6]]])
  |> Enum.sort(&amp;(PairComparer.compare(&amp;1, &amp;2) == :lt))
  |> Enum.with_index()

{_, packet1_index} = Enum.find(sorted, fn {e, _index} -> e == [[2]] end)
{_, packet2_index} = Enum.find(sorted, fn {e, _index} -> e == [[6]] end)

(packet1_index + 1) * (packet2_index + 1)
23111