Powered by AppSignal & Oban Pro

Day 12

2021/notebooks/day-12.livemd

Day 12

Setup

input = Aoc.get_input(12)
textarea = Kino.Input.textarea("Puzzle input", default: input)
test_textarea = Kino.Input.textarea("Test input")
small_test_textarea = Kino.Input.textarea("Small test input")
options = [
  puzzle: "Puzzle",
  test: "Test",
  small_test: "Small"
]

select = Kino.Input.select("Input source", options)
lines =
  select
  |> Kino.Input.read()
  |> case do
    :puzzle -> input
    :test -> test_textarea |> Kino.Input.read()
    :small_test -> small_test_textarea |> Kino.Input.read()
  end
  |> String.split(["\n"], trim: true)
map =
  lines
  |> Enum.map(&String.split(&1, "-", trim: true))
  |> Enum.reduce(%{}, fn [from, to], map ->
    map
    |> Map.update(from, MapSet.new([to]), &MapSet.put(&1, to))
    |> Map.update(to, MapSet.new([from]), &MapSet.put(&1, from))
  end)

Part 1

defmodule Day12 do
  def lowercase?(letters), do: String.downcase(letters) == letters

  def expand(_map, "end" = to, path, _), do: [to | path] |> Enum.reverse() |> Enum.join(",")

  def expand(map, to, path, visited) do
    path = [to | path]
    visited = MapSet.put(visited, to)

    map[to]
    |> Enum.reject(&(Day12.lowercase?(&1) && MapSet.member?(visited, &1)))
    |> Enum.map(&expand(map, &1, path, visited))
  end
end
Day12.expand(map, "start", [], MapSet.new())
|> List.flatten()
|> Enum.count()

Part 2

defmodule Day12 do
  def lowercase?(letters), do: String.downcase(letters) == letters

  def expand(_map, "end" = to, path, _, _), do: [to | path] |> Enum.reverse() |> Enum.join(",")

  def expand(map, to, path, visited, twice?) do
    path = [to | path]
    visited = MapSet.put(visited, to)

    map[to]
    |> Enum.map(fn to ->
      if lowercase?(to) && MapSet.member?(visited, to) do
        if twice? do
          []
        else
          case to do
            "start" -> []
            "end" -> []
            to -> expand(map, to, path, visited, true)
          end
        end
      else
        expand(map, to, path, visited, twice?)
      end
    end)
  end
end
Day12.expand(map, "start", [], MapSet.new(), false)
|> List.flatten()
|> Enum.count()