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

Day11

livebook/day-11.livemd

Day11

Setup

Mix.install(
  [
    {:kino, "~> 0.4.1"}
  ],
  consolidate_protocols: false
)

input = Kino.Input.textarea("Please paste your input:")

# 5483143223
# 2745854711
# 5264556173
# 6141336146
# 6357385478
# 4167524645
# 2176841721
# 6882881134
# 4846848554
# 5283751526

# 11111
# 19991
# 19191
# 19991
# 11111

# Input
2_682_551_651
3_223_134_263
5_848_471_412
7_438_334_862
8_731_321_573
6_415_233_574
5_564_726_843
6_683_456_445
8_582_346_112
4_617_588_236
lines =
  input
  |> Kino.Input.read()
  |> String.split(["\n"], trim: true)

grid =
  for {line, row} <- Enum.with_index(lines),
      {number, col} <- Enum.with_index(String.to_charlist(line)),
      into: %{} do
    {{col, row}, number - ?0}
  end

Map.update(grid, :lines, Enum.count(lines), &amp; &amp;1)

Part 1

defmodule Recursion do
  def energize({grid, blinks}, {row, col} = point) do
    cond do
      grid[point] == nil ->
        {grid, blinks}

      grid[point] > 9 ->
        {grid, blinks}

      grid[point] == 9 ->
        energize({Map.update(grid, point, nil, &amp;(&amp;1 + 1)), blinks + 1}, {row + 1, col})
        |> energize({row + 1, col + 1})
        |> energize({row, col + 1})
        |> energize({row - 1, col})
        |> energize({row - 1, col - 1})
        |> energize({row, col - 1})
        |> energize({row + 1, col - 1})
        |> energize({row - 1, col + 1})

      true ->
        {Map.update(grid, point, nil, &amp;(&amp;1 + 1)), blinks}
    end
  end

  def step(result, _count = 0) do
    result
  end

  def step({grid, blinks}, count) do
    {grid, blinks} =
      Map.keys(grid)
      |> Enum.reduce({grid, blinks}, fn point, {grid, blinks} ->
        energize({grid, blinks}, point)
      end)

    grid =
      grid
      |> Map.new(fn {point, value} ->
        cond do
          value > 9 -> {point, 0}
          true -> {point, value}
        end
      end)

    step({grid, blinks}, count - 1)
  end
end

{final_grid, blinks} = Recursion.step({grid, 0}, 100)

blinks

Part 2

Stream.iterate(1, &amp;(&amp;1 + 1))
|> Enum.reduce_while({grid, 0}, fn i, {grid, blink} ->
  {grid, blink} = Recursion.step({grid, blink}, 1)

  result =
    for {_, value} <- grid,
        value != 0,
        do: true

  cond do
    result == [] -> {:halt, i}
    true -> {:cont, {grid, blink}}
  end
end)