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

--- Day 12: Passage Pathing ---

2021/day12.livemd

— Day 12: Passage Pathing —

Setup

defmodule Setup do
  def get_input(prompt) do
    case IO.gets(prompt) do
      :eof -> ""
      line -> line <> get_input(prompt)
    end
  end
end
map =
  Setup.get_input("input")
  |> String.split(["-", "\n"], trim: true)
  |> then(fn string -> string ++ Enum.reverse(string) end)
  |> Enum.chunk_every(2)
  |> Enum.reduce(%{}, fn [a, b], map ->
    Map.update(map, a, [b], &amp;[b | &amp;1])
  end)
defmodule Submarine do
  def cavewalks(map, at \\ "start", had_extra_visit? \\ true)

  def cavewalks(_map, "end", _had_extra_visit?) do
    [["end"]]
  end

  def cavewalks(map, at, had_extra_visit?) do
    new_map = drop_small_cave(map, at)

    map
    |> Map.get(at)
    |> Enum.reduce([], fn cave, walks ->
      if had_extra_visit? do
        walks ++ cavewalks(new_map, cave, true)
      else
        if small_cave?(at) and at != "start" do
          walks ++ cavewalks(new_map, cave, false) ++ cavewalks(map, cave, true)
        else
          walks ++ cavewalks(new_map, cave, false)
        end
      end
    end)
    |> Enum.uniq()
    |> Enum.map(&amp;[at | &amp;1])
  end

  defp small_cave?(at), do: at == String.downcase(at)

  defp drop_small_cave(map, at) do
    if small_cave?(at) do
      for {cave, connections} when cave != at <- map, into: %{} do
        {cave, Enum.reject(connections, &amp;(&amp;1 == at))}
      end
    else
      map
    end
  end
end

Part1

Submarine.cavewalks(map) |> Enum.count()

Part2

Submarine.cavewalks(map, "start", false) |> Enum.count()