Powered by AppSignal & Oban Pro
Would you like to see your link here? Contact us

Day 10

10.livemd

Day 10

Section

example = """
89010123
78121874
87430965
96549874
45678903
32019012
01329801
10456732
"""

defmodule Day10 do
  def get_map(input) do
    for {row, y} <- input |> String.split("\n", trim: true) |> Enum.with_index(),
        {h, x} <- row |> String.split("", trim: true) |> Enum.with_index(),
        into: %{} do
      {{x, y}, String.to_integer(h)}
    end
  end

  def get_starts(input) do
    for {row, y} <- input |> String.split("\n", trim: true) |> Enum.with_index(),
        {"0", x} <- row |> String.split("", trim: true) |> Enum.with_index() do
      {x, y}
    end
  end

  def solve(input, part) do
    map = get_map(input)
    starts = get_starts(input)

    starts
    |> Enum.map(fn {x, y} ->
      move(x, y, 0, map, [])
      |> List.flatten()
      |> Enum.filter(&amp; &amp;1)
      |> Enum.uniq_by(fn result ->
        case part do
          :part1 -> result.finished_at
          :part2 -> result
        end
      end)
      |> length()
    end)
    |> Enum.sum()
  end

  def move(x, y, h, map, path) do
    for {nx, ny} <- [{x, y + 1}, {x, y - 1}, {x + 1, y}, {x - 1, y}] do
      nh = Map.get(map, {nx, ny})

      cond do
        is_nil(nh) ->
          nil

        nh == 9 &amp;&amp; nh - h == 1 ->
          %{finished_at: {nx, ny}, path: [{nx, ny, nh} | path]}

        nh - h == 1 ->
          move(nx, ny, nh, map, [{nx, ny, nh} | path])

        true ->
          nil
      end
    end
  end
end

Day10.solve(example, :part1)
Day10.solve(example, :part2)