Day 12
input =
File.read!("day12.txt")
|> String.split("\n")
|> Enum.map(&String.split(&1, "-"))
graph =
Enum.reduce(input, %{}, fn [a, b], acc ->
acc
|> Map.update(a, [b], &[b | &1])
|> Map.update(b, [a], &[a | &1])
end)
defmodule Day12 do
def dfs(graph, start, finish), do: dfs(graph, start, finish, [start])
defp dfs(_graph, vertex, vertex, _visited), do: 1
defp dfs(graph, vertex, finish, visited) do
(graph[vertex] -- visited)
|> Enum.reduce(0, fn vertex, acc ->
visited = if small?(vertex), do: [vertex | visited], else: visited
acc + dfs(graph, vertex, finish, visited)
end)
end
def dfs2(graph, start, finish), do: dfs2(graph, start, finish, %{start => :inf})
defp dfs2(_graph, vertex, vertex, _visited), do: 1
defp dfs2(graph, vertex, finish, visited) do
(graph[vertex] -- keys(visited))
|> Enum.reduce(0, fn vertex, acc ->
visited = if small?(vertex), do: Map.update(visited, vertex, 1, &(&1 + 1)), else: visited
acc + dfs2(graph, vertex, finish, visited)
end)
end
defp keys(map) do
if Enum.any?(map, fn {_, v} -> v == 2 end) do
# there is already some vertex visited twice
Map.keys(map)
else
for {k, v} <- map, v > 1, do: k
end
end
defp small?(<> <> _), do: c in ?a..?z
end
{:module, Day12, <<70, 79, 82, 49, 0, 0, 15, ...>>, {:small?, 1}}
Task 1
Day12.dfs(graph, "start", "end")
4167
Task 2
Day12.dfs2(graph, "start", "end")
98441