Day 12
Mix.install([
{:kino, "~> 0.7.0"},
{:libgraph, "~> 0.16.0"}
])
example_input =
Kino.Input.textarea("example input:")
|> Kino.render()
real_input = Kino.Input.textarea("real input:")
Common
defmodule Heightmap do
def graph(map) do
for {coord, height} <- map, neighbor <- neighbors(coord), reduce: Graph.new() do
graph ->
if map[neighbor] <= height + 1 do
Graph.add_edge(graph, coord, neighbor)
else
graph
end
end
end
defp neighbors({i, j}) do
[
{i, j + 1},
{i + 1, j},
{i, j - 1},
{i - 1, j}
]
end
def new(rows) do
for {row, i} <- Enum.with_index(rows),
{col, j} <- Enum.with_index(row),
reduce: {%{}, nil, nil} do
{map, s, e} ->
case col do
?S -> {Map.put(map, {i, j}, ?a), {i, j}, e}
?E -> {Map.put(map, {i, j}, ?z), s, {i, j}}
height -> {Map.put(map, {i, j}, height), s, e}
end
end
end
end
parse = fn input ->
input
|> Kino.Input.read()
|> String.split("\n", trim: true)
|> Enum.map(&to_charlist/1)
end
Part 1
{map, s, e} =
real_input
|> then(parse)
|> Heightmap.new()
Heightmap.graph(map)
|> Graph.dijkstra(s, e)
|> length()
|> Kernel.-(1)
Part 2
{map, _, e} =
real_input
|> then(parse)
|> Heightmap.new()
graph = Heightmap.graph(map)
map
|> Enum.flat_map(&if(elem(&1, 1) == ?a, do: [elem(&1, 0)], else: []))
|> Enum.flat_map(fn s ->
case Graph.dijkstra(graph, s, e) do
nil -> []
list -> [length(list) - 1]
end
end)
|> Enum.sort()
|> hd()