Powered by AppSignal & Oban Pro

Advent of Code 2021 - Day 10

2021/day10.livemd

Advent of Code 2021 - Day 10

Setup

Mix.install([
  {:kino, "~> 0.4.1"}
])
:ok
example_input = Kino.Input.textarea("Please enter the example input:")
my_input = Kino.Input.textarea("Please enter your input:")
defmodule Parser do
  def parse_input(input) do
    input
    |> String.split("\n", trim: true)
    |> Enum.map(&String.to_charlist/1)
  end
end

example_input =
  example_input
  |> Kino.Input.read()
  |> Parser.parse_input()

my_input =
  my_input
  |> Kino.Input.read()
  |> Parser.parse_input()

:ok
:ok

Part 1

defmodule Day10.Part1 do
  @illegal_character_points %{
    ?) => 3,
    ?] => 57,
    ?} => 1197,
    ?> => 25137
  }

  def solve(input) do
    input
    |> Enum.map(&find_illegal_character(&1, []))
    |> Enum.map(&Map.get(@illegal_character_points, &1, 0))
    |> Enum.sum()
  end

  @chunk_pairs %{
    ?( => ?),
    ?[ => ?],
    ?{ => ?},
    ?< => ?>
  }
  def end_char(char) do
    @chunk_pairs[char]
  end

  defp find_illegal_character([], _stack), do: nil

  defp find_illegal_character([char | line], stack) do
    end_char = @chunk_pairs[char]

    if end_char == nil do
      [start_char | stack] = stack

      if char != @chunk_pairs[start_char] do
        char
      else
        find_illegal_character(line, stack)
      end
    else
      find_illegal_character(line, [char | stack])
    end
  end
end

Day10.Part1.solve(my_input)
271245

Part 2

defmodule Day10.Part2 do
  @autocomplete_character_points %{
    ?) => 1,
    ?] => 2,
    ?} => 3,
    ?> => 4
  }

  def solve(input) do
    input
    |> Enum.map(&amp;autocomplete_characters(&amp;1, []))
    |> Enum.filter(&amp;(&amp;1 != nil))
    |> Enum.map(&amp;score_autocomplete/1)
    |> Enum.sort()
    |> then(&amp;Enum.at(&amp;1, div(Enum.count(&amp;1), 2)))
  end

  defp autocomplete_characters([], []), do: nil

  defp autocomplete_characters([], stack) do
    Enum.map(stack, &amp;Day10.Part1.end_char/1)
  end

  defp autocomplete_characters([char | line], stack) do
    end_char = Day10.Part1.end_char(char)

    if end_char == nil do
      [start_char | stack] = stack

      if char != Day10.Part1.end_char(start_char) do
        nil
      else
        autocomplete_characters(line, stack)
      end
    else
      autocomplete_characters(line, [char | stack])
    end
  end

  defp score_autocomplete(autocomplete) do
    Enum.reduce(autocomplete, 0, fn char, total ->
      score = @autocomplete_character_points[char]
      total * 5 + score
    end)
  end
end

Day10.Part2.solve(my_input)
1685293086