diff --git a/2024/day11.exs b/2024/day11.exs index 261069e..5deed00 100644 --- a/2024/day11.exs +++ b/2024/day11.exs @@ -1,34 +1,36 @@ #!/usr/bin/env elixir defmodule Day11 do def part1(stones) do - 1..25 - |> Enum.reduce(stones, fn _, stones -> blink(stones) end) - |> Enum.count() + blink(stones, 25) end - def blink([]), do: [] - def blink([0 | rest]), do: [1 | blink(rest)] - - def blink([stone | rest]) do - string = Integer.to_string(stone) - size = byte_size(string) - - if rem(size, 2) == 0 do - string - |> String.split_at(div(size, 2)) - |> Tuple.to_list() - |> Enum.map(&String.to_integer/1) - |> Kernel.++(blink(rest)) - else - [stone |> Kernel.*(2024) | blink(rest)] - end - end - - # probably have to track the changes rather than keep the whole list? def part2(stones) do - 1..75 - |> Enum.reduce(stones, fn _, stones -> blink(stones) end) - |> Enum.count() + blink(stones, 75) + end + + def blink(stones, 0), do: stones |> Map.values() |> Enum.sum() + + def blink(stones, times) do + stones + |> Enum.reduce(%{}, fn + {0, count}, next -> + Map.update(next, 1, count, &(&1 + count)) + + {stone, count}, next -> + string = Integer.to_string(stone) + size = byte_size(string) + + if rem(size, 2) == 0 do + {a, b} = String.split_at(string, div(size, 2)) + + next + |> Map.update(String.to_integer(a), count, &(&1 + count)) + |> Map.update(String.to_integer(b), count, &(&1 + count)) + else + Map.update(next, stone * 2024, count, &(&1 + count)) + end + end) + |> blink(times - 1) end def input do @@ -37,6 +39,7 @@ defmodule Day11 do input |> String.split([" ", "\n"], trim: true) |> Enum.map(&String.to_integer/1) + |> Enum.frequencies() else _ -> :error end