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

Day 10

advent_of_code/2021/day-10.livemd

Day 10

Setup

Mix.install([
  {:kino, "~> 0.5.0"}
])
input = Kino.Input.textarea("Input:")
defmodule Syntax do
  def parse(line), do: parse(line, [])

  # Opening
  defp parse(<rest::binary>, stack), do: parse(rest, [?) | stack])
  defp parse(<rest::binary>, stack), do: parse(rest, [?] | stack])
  defp parse(<rest::binary>, stack), do: parse(rest, [?} | stack])
  defp parse(<rest::binary>, stack), do: parse(rest, [?> | stack])

  # Closing
  defp parse(<>, [char | stack]), do: parse(rest, stack)

  # Base/error cases
  defp parse(<>, _stack), do: {:corrupted, char}
  defp parse(<<>>, []), do: :ok
  defp parse(<<>>, stack), do: {:incomplete, stack}
end

lines = input |> Kino.Input.read() |> String.split("\n", trim: true)
:ok

Part 1

points = %{
  ?) => 3,
  ?] => 57,
  ?} => 1197,
  ?> => 25137
}

Enum.sum(
  for line <- lines,
      {:corrupted, char} <- [Syntax.parse(line)],
      do: Map.fetch!(points, char)
)

Part 2

points = %{
  ?) => 1,
  ?] => 2,
  ?} => 3,
  ?> => 4
}

scores =
  Enum.sort(
    for line <- lines,
        {:incomplete, chars} <- [Syntax.parse(line)],
        do: Enum.reduce(chars, 0, fn char, acc -> acc * 5 + Map.fetch!(points, char) end)
  )

Enum.fetch!(scores, div(length(scores), 2))