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

Advent 2022 - Day 13

day13.livemd

Advent 2022 - Day 13

Mix.install([
  {:kino, github: "livebook-dev/kino"}
])
:ok

Setup

input = Kino.Input.textarea("Please paste your input file:")
pairs =
  input
  |> Kino.Input.read()
  |> String.split("\n\n")
  |> Enum.map(&String.split(&1, "\n"))
[
  ["[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]"]
]
pairs =
  pairs
  |> Enum.map(fn pair ->
    pair
    |> Enum.map(&Code.eval_string/1)
    |> Enum.map(&elem(&1, 0))
  end)
[
  [[1, 1, 3, 1, 1], [1, 1, 5, 1, 1]],
  [[[1], [2, 3, 4]], [[1], 4]],
  ['\t', [[8, 7, 6]]],
  [[[4, 4], 4, 4], [[4, 4], 4, 4, 4]],
  ['\a\a\a\a', '\a\a\a'],
  [[], [3]],
  [[[[]]], [[]]],
  [[1, [2, [3, [4, [5, 6, 7]]]], 8, 9], [1, [2, [3, [4, [5, 6, 0]]]], 8, 9]]
]

Utils

defmodule PacketValidator do
  def validate(a, b) when is_integer(a) and is_list(b), do: validate([a], b)
  def validate(a, b) when is_list(a) and is_integer(b), do: validate(a, [b])
  def validate([], []), do: nil
  def validate(_a, []), do: false
  def validate([], _b), do: true

  def validate(a, b) when is_list(a) and is_list(b) do
    resp = validate(hd(a), hd(b))
    if resp == nil, do: validate(tl(a), tl(b)), else: resp
  end

  def validate(a, b) when is_integer(a) and is_integer(b) do
    cond do
      a == b -> nil
      a > b -> false
      a < b -> true
    end
  end
end
{:module, PacketValidator, <<70, 79, 82, 49, 0, 0, 8, ...>>, {:validate, 2}}

Part 1

pairs
|> Enum.map(fn [l, r] ->
  PacketValidator.validate(l, r)
end)
|> Enum.with_index()
|> Enum.filter(fn {valid, _index} -> valid end)
|> Enum.map(&amp;(elem(&amp;1, 1) + 1))
|> Enum.sum()
13

Part 2

all_packets = pairs |> Enum.reduce(&amp;(&amp;1 ++ &amp;2))

additional_packet_1 = [[2]]
additional_packet_2 = [[6]]

all_packets_plus_extra = all_packets ++ [additional_packet_1, additional_packet_2]

sorted = all_packets_plus_extra |> Enum.sort(&amp;PacketValidator.validate/2)
[
  [],
  [[]],
  [[[]]],
  [1, 1, 3, 1, 1],
  [1, 1, 5, 1, 1],
  [[1], [2, 3, 4]],
  [1, [2, [3, [4, [5, 6, 0]]]], 8, 9],
  [1, [2, [3, [4, [5, 6, 7]]]], 8, 9],
  [[1], 4],
  [[2]],
  [3],
  [[4, 4], 4, 4],
  [[4, 4], 4, 4, 4],
  [[6]],
  '\a\a\a',
  '\a\a\a\a',
  [[8, 7, 6]],
  '\t'
]
first = Enum.find_index(sorted, &amp;(&amp;1 == additional_packet_1)) + 1
second = Enum.find_index(sorted, &amp;(&amp;1 == additional_packet_2)) + 1

first * second
140