This one wasn’t too bad I actually ended up solving part 2 first, and had to work around it in part 1 to get the answer there!
input = ""
|> String.trim()
tiles = input |> String.split("\n")
|> Stream.with_index()
|> Enum.flat_map(fn {line, l_idx} ->
line
|> String.trim()
|> String.graphemes()
|> Stream.with_index()
|> Enum.map(fn {".", idx} -> {{idx, l_idx}, nil}
{c, idx} -> {{idx, l_idx}, c |> String.to_integer()} end)
end)
|> Enum.into(Map.new())
grid = Grid2D.new(
input |> String.split("\n") |> Enum.at(0) |> String.trim() |> String.length(),
input |> String.trim() |> String.split("\n") |> Enum.count()
)
defmodule TrailFinder do
def find_trails(input, tiles, grid) do
tiles
|> Stream.filter(fn {_, v} -> v == 0 end)
|> Enum.map(fn {k, _} -> {k, find_trails(input, tiles, grid, k, 0, [])} end)
end
def find_trails(_, _, _, p, 9, acc), do: [[{p, 9} | acc]]
def find_trails(input, tiles, grid, start, height, acc) do
Grid2D.neighbors(start, grid, :straight)
|> Enum.filter(fn p -> Map.get(tiles, p) == height + 1 end)
|> Enum.flat_map(fn p ->
find_trails(input, tiles, grid, p, height + 1, [{start, height} | acc])
end)
end
end
TrailFinder.find_trails(input, tiles, grid)
|> Enum.map(fn {s, l} -> {s, for [peak |_] <- l, into: MapSet.new do peak end } end)
|> Enum.map(fn {_, s} -> MapSet.size(s) end)
|> Enum.sum()
TrailFinder.find_trails(input, tiles, grid)
|> Stream.map(fn {_, l} -> l |> Enum.count end)
|> Enum.sum()