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

--- Day 11: Dumbo Octopus ---

2021/day11.livemd

— Day 11: Dumbo Octopus —

Setup

defmodule Setup do
  def get_input(prompt) do
    case IO.gets(prompt) do
      :eof -> ""
      line -> line <> get_input(prompt)
    end
  end
end
defmodule Setup do
  def get_input(prompt) do
    case IO.gets(prompt) do
      :eof -> ""
      line -> line <> get_input(prompt)
    end
  end

  def parse_input(binary) do
    binary
    |> String.split("\n", trim: true)
    |> Enum.map(fn line ->
      line
      |> String.split("", trim: true)
      |> Enum.map(&amp;String.to_integer/1)
    end)
    |> then(fn input ->
      {height, width} = {length(input), length(hd(input))}

      for x <- 0..(height - 1), y <- 0..(width - 1), into: %{} do
        {{x, y}, get_in(input, [Access.at(x), Access.at(y)])}
      end
    end)
  end
end
defmodule DumboOcto do
  def step(map) do
    map = map |> Map.new(fn {p, e} -> {p, e + 1} end)

    for {point, 10} <- map, reduce: map do
      map -> flash(point, map)
    end
  end

  def flash(point, map) do
    if energy = map[point] do
      case energy do
        0 ->
          map

        n when n >= 9 ->
          map
          |> Map.put(point, 0)
          |> then(fn map ->
            Enum.reduce(adjacent(point), map, &amp;flash/2)
          end)

        n ->
          Map.put(map, point, n + 1)
      end
    else
      map
    end
  end

  defp adjacent({x, y}) do
    for x2 <- (x - 1)..(x + 1), y2 when {x2, y2} != {x, y} <- (y - 1)..(y + 1), do: {x2, y2}
  end
end
Setup.get_input("input")
|> Setup.parse_input()
|> then(fn map ->
  Enum.reduce(1..100, {0, map}, fn _, {score, map} ->
    map
    |> DumboOcto.step()
    |> then(fn map ->
      {
        Enum.count(map, fn {_, v} -> v == 0 end) + score,
        map
      }
    end)
  end)
end)
Stream.iterate(0, &amp;(&amp;1 + 1))
|> Enum.reduce_while(map, fn step, map ->
  if map |> Map.values() |> Enum.all?(&amp;(&amp;1 == 0)) do
    {:halt, step}
  else
    {:cont, DumboOcto.step(map)}
  end
end)