Powered by AppSignal & Oban Pro

Day 10

2021/day10.livemd

Day 10

input =
  File.stream!("day10.txt")
  |> Stream.map(&String.trim/1)

defmodule Day10 do
  @parens %{?( => ?), ?[ => ?], ?< => ?>, ?{ => ?}}

  def parse(input), do: parse(input, [])

  defp parse(<<c>> <> rest, stack) when c in '([{<', do: parse(rest, [@parens[c] | stack])
  defp parse(<<c>> <> rest, [c | stack]), do: parse(rest, stack)
  defp parse(<<>>, []), do: :ok
  defp parse(<<>>, rest), do: {:incomplete, rest}
  defp parse(<<c>> <> _, _), do: {:unexpected, [c]}
end
{:module, Day10, <<70, 79, 82, 49, 0, 0, 7, ...>>, {:parse, 2}}

Task 1

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

input
|> Enum.map(&Day10.parse/1)
|> Enum.map(fn
  {:unexpected, [c]} -> points[c]
  _ -> 0
end)
|> Enum.sum()
288291

Task 2

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

median = fn list ->
  sorted = Enum.sort(list)
  middle = div(length(list), 2)

  Enum.at(sorted, middle)
end

input
|> Enum.map(&Day10.parse/1)
|> Enum.flat_map(fn
  {:incomplete, rest} ->
    [
      Enum.reduce(rest, 0, fn c, acc ->
        acc * 5 + points[c]
      end)
    ]

  _ ->
    []
end)
|> median.()
820045242