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

Day 11

livebook/11.livemd

Day 11

Part 1

# input = "125 17"
input = "2 77706 5847 9258441 0 741 883933 12"
defmodule U do
  def parse(input) do
    input  |> String.split() |> Enum.map(&String.to_integer/1)
  end
end
stones = U.parse(input)
defmodule P1 do
  require Integer

  def steps(stones), do: steps(stones, 25)

  def steps(stones, 0), do: Enum.count(stones)

  def steps(stones, i) do
    step(stones) |> steps(i - 1)
  end

  def step(stones) do
    for stone <- stones,
        stones = rule1(stone) || rule2(stone) || rule3(stone),
        stone <- stones do
      stone
    end
  end

  def rule1(0), do: [1]
  def rule1(_), do: nil

  def rule2(stone) do
    s = Integer.to_string(stone)
    l = String.length(s)

    if Integer.is_even(l) do
      [
        String.slice(s, 0, div(l, 2)) |> String.to_integer(),
        String.slice(s, div(l, 2), div(l, 2)) |> String.to_integer()
      ]
    end
  end

  def rule3(stone), do: [stone * 2024]
end
P1.steps(stones)

Part 2

defmodule P2 do
  require Integer

  def steps(stones), do: steps(Map.from_keys(stones, 1), 75)

  def steps(stones, 0), do: Map.values(stones) |> Enum.sum()

  def steps(stones, i) do
    # IO.inspect({25 - i, Map.values(stones) |> Enum.sum(), stones})
    
    Enum.reduce(stones, %{}, fn {n, c}, m ->
      u = fn x -> x + c end
      s = Integer.to_string(n)
      l = String.length(s)
      cond do
        n == 0 ->
          Map.update(m, 1, c, u)

        Integer.is_even(l) ->
          h = div(l, 2)

          m
          |> Map.update(String.slice(s, 0, h) |> String.to_integer(), c, u)
          |> Map.update(String.slice(s, h, h) |> String.to_integer(), c, u)

        true ->
          Map.update(m, n * 2024, c, u)
      end
    end)
    |> steps(i - 1)
  end
end
P2.steps(stones)