Day 12: Passage Pathing
Mix.install([:kino])
input = Kino.Input.textarea("Please paste your input:")
Setup
inputs =
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&(&1 |> String.split("-")))
|> Enum.reduce(%{}, fn [a, b], map ->
map
|> Map.update(a, [b], &[b | &1])
|> Map.update(b, [a], &[a | &1])
end)
Part 1
https://adventofcode.com/2021/day/12
Solve: Part 1
defmodule Day12.Part1 do
def run(connections) do
do_run(connections, "start", [], [])
end
def do_run(_connections, "end", path, results) do
path = ["end" | path] |> Enum.reverse()
[path | results]
end
def do_run(connections, current_cave, path, results) do
{next_caves, connections} =
case cave_type(current_cave) do
:big -> {connections |> Map.get(current_cave, []), connections}
:small -> connections |> Map.pop(current_cave, [])
end
case next_caves do
[] ->
results
next_caves ->
next_caves
|> Enum.reduce(results, fn next_cave, results ->
do_run(connections, next_cave, [current_cave | path], results)
end)
end
end
defp cave_type(name) do
case Regex.match?(~r/[A-Z]+/, name) do
true -> :big
false -> :small
end
end
end
inputs
|> Day12.Part1.run()
|> Enum.count()
Part 2
https://adventofcode.com/2021/day/12#part2
Solve: Part 2
defmodule Day12.Part2 do
def run(connections) do
do_run(connections, "start", true, [], [])
end
def do_run(_connections, "end", _twice_flag, path, results) do
path = ["end" | path] |> Enum.reverse()
[path | results]
end
def do_run(connections, current_cave, twice_flag, path, results) do
args =
connections
|> Map.get(current_cave, [])
|> Enum.map(fn next_cave ->
case {twice_flag, cave_type(current_cave)} do
{twice_flag, :big} ->
[{next_cave, connections, twice_flag}]
{true, :small} ->
[
{next_cave, connections, false},
{next_cave, connections |> Map.delete(current_cave), true}
]
{false, :small} ->
[{next_cave, connections |> Map.delete(current_cave), false}]
{twice_flag, :start} ->
[{next_cave, connections |> Map.delete(current_cave), twice_flag}]
end
end)
|> List.flatten()
case args do
[] ->
results
args ->
args
|> Enum.reduce(results, fn {next_cave, connections, twice_flag}, results ->
do_run(connections, next_cave, twice_flag, [current_cave | path], results)
end)
end
end
defp cave_type("start"), do: :start
defp cave_type(name) do
case Regex.match?(~r/[A-Z]+/, name) do
true -> :big
false -> :small
end
end
end
inputs
|> Day12.Part2.run()
|> Enum.uniq()
|> Enum.count()