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

Day - 12

day-12.livemd

Day - 12

Setup

Mix.install([
  {:kino, "~> 0.4.1"}
])
input = Kino.Input.textarea("Please enter your Input")
edges =
  input
  |> Kino.Input.read()
  |> String.split("\n", trim: true)
  |> Enum.reduce(%{}, fn line, acc ->
    [left, right] = String.split(line, "-")
    acc = Map.update(acc, left, [right], &[right | &1])

    if left == "start" or right == "end" do
      acc
    else
      Map.update(acc, right, [left], &[left | &1])
    end
  end)

:ok

Part 1

defmodule Once do
  def recur(edges) do
    recur(edges["start"], edges, MapSet.new(["start"]), ["start"], 0)
  end

  defp recur(["end" | caves], edges, seen, path, count) do
    recur(caves, edges, seen, path, count + 1)
  end

  defp recur([cave | caves], edges, seen, path, count) do
    count =
      cond do
        cave in seen ->
          count

        small_cave?(cave) ->
          recur(edges[cave], edges, MapSet.put(seen, cave), [cave | path], count)

        true ->
          recur(edges[cave], edges, seen, [cave | path], count)
      end

    recur(caves, edges, seen, path, count)
  end

  defp recur([], _edges, _seen, _path, count), do: count

  defp small_cave?(cave), do: String.downcase(cave, :ascii) == cave
end

Once.recur(edges)

Part 2

defmodule Twice do
  def recur(edges) do
    recur(edges["start"], edges, MapSet.new(["start"]), false, ["start"], 0)
  end

  defp recur(["end" | caves], edges, seen, once?, path, count) do
    recur(caves, edges, seen, once?, path, count + 1)
  end

  defp recur([cave | caves], edges, seen, once?, path, count) do
    count =
      cond do
        cave == "start" or (cave in seen and once?) ->
          count

        cave in seen ->
          recur(edges[cave], edges, MapSet.put(seen, cave), true, [cave | path], count)

        small_cave?(cave) ->
          recur(edges[cave], edges, MapSet.put(seen, cave), once?, [cave | path], count)

        true ->
          recur(edges[cave], edges, seen, once?, [cave | path], count)
      end

    recur(caves, edges, seen, once?, path, count)
  end

  defp recur([], _edges, _seen, _once?, _path, count), do: count

  defp small_cave?(cave), do: String.downcase(cave, :ascii) == cave
end

# Twice.recur(edges)