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

Advent of Code - Day 11

2024/day-11.livemd

Advent of Code - Day 11

Mix.install([{:kino, github: "livebook-dev/kino"}])

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

Part 1

input = Kino.Input.read(kino_input)

defmodule Blinker do
  def blink(arrangement, 0), do: arrangement
  
  def blink(arrangement, count) do
    new_arrangement = 
      arrangement
      |> Enum.flat_map(fn stone_engraving -> 
        case Integer.digits(stone_engraving) do
          [0] -> [1]
            
          digits when rem(length(digits), 2) == 0 ->
            {half1, half2} = Enum.split(digits, div(length(digits), 2))
            [Integer.undigits(half1), Integer.undigits(half2)]
            
          _ -> [stone_engraving * 2024]
        end
      end)

    blink(new_arrangement, count - 1)
  end
end

input
|> String.split(" ")
|> Enum.map(&String.to_integer/1)
|> Blinker.blink(25)
|> Enum.count()

Part 2

input = Kino.Input.read(kino_input)

defmodule Blinker2 do
  def blink(arrangement, 0), do: arrangement
  
  def blink(arrangement, count) do
    new_arrangement =
      arrangement
      |> Map.to_list()
      |> do_blink(%{})

    blink(new_arrangement, count - 1)
  end

  def do_blink([], acc), do: acc

  def do_blink([{0, count} |  rest], acc) do
    do_blink(rest, Map.update(acc, 1, count, &(&1 + count)))
  end

  def do_blink([{stone_engraving, count} | rest], acc) do
    digits = Integer.digits(stone_engraving)

    if rem(Enum.count(digits), 2) == 0 do
      {half1, half2} = Enum.split(digits, div(Enum.count(digits), 2))

      new_acc =
        acc
        |> Map.update(Integer.undigits(half1), count, &(&1 + count))
        |> Map.update(Integer.undigits(half2), count, &(&1 + count))

      do_blink(rest, new_acc)
    else
      do_blink(rest, Map.update(acc, stone_engraving * 2024, count, &(&1 + count)))
    end
  end
end

input
|> String.split(" ")
|> Enum.reduce(%{}, fn stone_engraving, acc ->
  Map.update(acc, String.to_integer(stone_engraving), 1, &(&1 + 1))
end)
|> Blinker2.blink(75)
|> Map.values()
|> Enum.sum()