Advent of Code 2023 - Day 10
Mix.install([
{:kino, "~> 0.11.0"},
{:kino_aoc, github: "ljgago/kino_aoc"},
{:libgraph, "~> 0.16.0"},
{:topo, "~> 1.0"}
])
Input
{:ok, puzzle_input} =
KinoAOC.download_puzzle("2023", "10", System.fetch_env!("LB_AOC_SESSION"))
tiles =
puzzle_input
|> String.split("\n", trim: true)
|> Enum.map(&String.split(&1, "", trim: true))
grid =
for {row, y} <- Enum.with_index(tiles),
{tile, x} <- Enum.with_index(row),
into: %{},
do: {{x, y}, tile}
{start, _} = Enum.find(grid, fn {_, tile} -> tile == "S" end)
n = fn {x, y} -> {x, y - 1} end
e = fn {x, y} -> {x + 1, y} end
s = fn {x, y} -> {x, y + 1} end
w = fn {x, y} -> {x - 1, y} end
adjacents = fn
_p, "." -> []
_p, "S" -> []
p, "|" -> [n.(p), s.(p)]
p, "-" -> [w.(p), e.(p)]
p, "L" -> [n.(p), e.(p)]
p, "J" -> [n.(p), w.(p)]
p, "7" -> [w.(p), s.(p)]
p, "F" -> [e.(p), s.(p)]
end
graph =
for {{x, y}, tile} <- grid, reduce: Graph.new() do
acc ->
adjacents.({x, y}, tile)
|> Enum.reduce(acc, fn a, acc -> Graph.add_edge(acc, {x, y}, a) end)
end
loop =
graph
|> Graph.in_neighbors(start)
|> Enum.reduce(graph, fn n, g ->
Graph.add_edge(g, start, n)
end)
|> Graph.reachable_neighbors([start])
Part 1
length(loop) |> div(2)
Part 2
geoloop = %Geo.Polygon{coordinates: [loop]}
grid
|> Map.keys()
|> Stream.reject(&(&1 in loop))
|> Stream.map(&Topo.contains?(geoloop, &1))
|> Enum.count(& &1)