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)