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

Day 10

livebook/10.livemd

Day 10

Part 1

# input = File.stream!("10/example.txt")
input = File.stream!("10/input.txt")
defmodule U do
  def parse(input) do
    {_, map } = Enum.reduce(input, {0, %{}}, fn line, {line_no, map} ->
      {_, map} = Enum.reduce(String.codepoints(line), {0, map}, fn 
        "\n", acc -> acc
        char, {col, map} -> 
        {col + 1, Map.put(map, {line_no, col}, String.to_integer(char))}
      end)
      {line_no + 1, map}
    end)
    map
  end
end
map = U.parse(input)
defmodule P1 do
  def solve(map) do
    starts = starts(map)
    trailheads = trailheads(starts, map)
    Enum.reduce(trailheads, 0, fn {_, reached}, acc ->
      acc + Enum.count(reached)
    end)
  end
  
  def starts(map) do
    for {pos, h} <- map,
        h == 0 do
      pos
    end
  end

  def trailheads(positions, map) do
    for pos <- positions do
      {pos, trailhead(pos, map, MapSet.new())}
    end
  end

  def trailheads(positions, map, reached) do
    Enum.reduce(positions, reached, fn pos, reached ->
      trailhead(pos, map, reached)
    end)
  end

  def trailhead(pos, map, reached) do
    h_cur = map[pos]

    # IO.inspect({pos, h_cur, visited})

    if h_cur == 9 do
      MapSet.put(reached, pos)
    else
      next_positions(pos, map) |> trailheads(map, reached)
    end
  end

  def next_positions({x, y} = pos, map) do
    h_cur = map[pos]

    for pos_next <- [{x + 1, y}, {x, y + 1}, {x - 1, y}, {x, y - 1}],
        h_next = map[pos_next],
        h_next != nil &amp;&amp; h_next - h_cur == 1 do
      pos_next
    end
  end
end
P1.solve(map)
defmodule P2 do
  def solve(map) do
    starts = P1.starts(map)
    trailheads = trailheads(starts, map)
    Enum.reduce(trailheads, 0, fn {_, reached}, acc ->
      acc + Enum.count(reached)
    end)
  end

  def trailheads(positions, map) do
    for pos <- positions do
      {pos, trailhead(pos, map, [], MapSet.new())}
    end
  end

  def trailheads(positions, map, path, reached) do
    Enum.reduce(positions, reached, fn pos, reached ->
      trailhead(pos, map, path, reached)
    end)
  end

  def trailhead(pos, map, path, reached) do
    h_cur = map[pos]

    if h_cur == 9 do
      MapSet.put(reached, [pos | path])
    else
      P1.next_positions(pos, map) |> trailheads(map, [pos | path], reached)
    end
  end

end
P2.solve(map)