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

Advent of Code 2024 Day 11 Part 2

2024_day11_part2.livemd

Advent of Code 2024 Day 11 Part 2

Mix.install([
  {:kino_aoc, "~> 0.1"}
])

Get Inputs

{:ok, puzzle_input} =
  KinoAOC.download_puzzle("2024", "11", System.fetch_env!("LB_SESSION"))

My answer

small_sample_input = "0 1 10 99 999"
stones =
  small_sample_input
  |> String.split(" ")
  |> Enum.map(&String.to_integer(&1))
stone = 99

digits = stone |> :math.log10() |> floor() |> Kernel.+(1)
half_power = :math.pow(10, div(digits, 2)) |> round()
{div(stone, half_power), rem(stone, half_power)}
defmodule BlinkCounter do
  def start_link do
    if :ets.info(:blink_count_cache) != :undefined do
      :ets.delete(:blink_count_cache)
    end

    :ets.new(:blink_count_cache, [:named_table, :public, :set])
    :ok
  end

  def blink(0), do: [1]
  def blink(stone) do
    digits = :math.log10(stone) |> floor() |> Kernel.+(1)
    if rem(digits, 2) == 0 do
      half_power = :math.pow(10, div(digits, 2)) |> round()
      left = div(stone, half_power)
      right = rem(stone, half_power)
      [left, right]
    else
      [stone * 2024]
    end
  end

  def count_expansions(_, 0) do
    1
  end

  def count_expansions(stone, steps) when steps > 0 do
    case :ets.lookup(:blink_count_cache, {stone, steps}) do
      [{_, count}] ->
        count

      [] ->
        result =
          blink(stone)
          |> Enum.reduce(0, fn next_stone, acc ->
            acc + count_expansions(next_stone, steps - 1)
          end)

        :ets.insert(:blink_count_cache, {{stone, steps}, result})
        result
    end
  end
end
BlinkCounter.start_link()
1..6
|> Enum.reduce([0], fn _, acc_stones ->
  acc_stones
  |> Enum.flat_map(fn stone ->
    BlinkCounter.blink(stone)
  end)
  |> IO.inspect()
end)
|> length()
BlinkCounter.count_expansions(0, 6)
stones
|> Enum.reduce(0, fn stone, acc ->
  acc + BlinkCounter.count_expansions(stone, 1)
end)
stones =
  "125 17"
  |> String.split(" ")
  |> Enum.map(&String.to_integer(&1))
stones
|> Enum.reduce(0, fn stone, acc ->
  acc + BlinkCounter.count_expansions(stone, 6)
end)
stones
|> Enum.reduce(0, fn stone, acc ->
  acc + BlinkCounter.count_expansions(stone, 25)
end)
stones =
  puzzle_input
  |> String.split(" ")
  |> Enum.map(&String.to_integer(&1))

stones
|> Enum.reduce(0, fn stone, acc ->
  acc + BlinkCounter.count_expansions(stone, 75)
end)