defmodule Day10 do def run do map = File.read!("data.txt") |> String.trim() |> String.split("\n") |> Enum.map(fn el -> String.graphemes(el) |> Enum.map(&String.to_integer/1) end) height = length(map) width = length(hd(map)) trailheads = Enum.concat(map) |> Enum.with_index() |> Enum.filter(fn {el, _} -> el == 0 end) |> Enum.map(fn {_, idx} -> {div(idx, height), rem(idx, width)} end) paths1 = Enum.reduce(trailheads, 0, fn th, acc -> (walk(th, map) |> List.flatten() |> Enum.uniq() |> length) + acc end) dbg(paths1) # same as part one, just don't uniq() them paths2 = Enum.reduce(trailheads, 0, fn th, acc -> (walk(th, map) |> List.flatten() |> length) + acc end) dbg(paths2) end defp walk(coord, map) do value = element_at(coord, map) if value == 9 do coord else # find the coords of all neighbors neighbors(coord) # filter by whether the element is 1 greater |> Enum.filter(fn c -> element_at(c, map) == value + 1 end) # add this path to the list. it'll be empty and then flattened away if it doesn't reach the top |> Enum.reduce([], fn el, acc -> [walk(el, map) | acc] end) end end defp neighbors({x, y}) do [{-1, 0}, {0, 1}, {1, 0}, {0, -1}] |> Enum.map(fn {dx, dy} -> {x + dx, y + dy} end) |> Enum.reject(fn {x2, y2} -> x2 < 0 or y2 < 0 end) end defp element_at({x, y}, map) do row = Enum.at(map, x) if is_nil(row), do: nil, else: Enum.at(row, y) end end Day10.run()