defmodule Day11 do
def part1(data) do
parse_and_solve(data, 25)
end
def part2(data) do
parse_and_solve(data, 75)
end
defp parse_and_solve(data, count) do
data
|> String.split([" ", "\n"], trim: true)
|> Enum.map(&String.to_integer/1)
|> solve(count)
|> elem(0)
end
defp solve(nums, rem, cache \\ %{})
defp solve(nums, 0, cache), do: {Enum.count(nums), cache}
defp solve([h], rem, cache) do
key = {h, rem}
case Map.fetch(cache, key) do
{_, res} ->
{res, cache}
:error ->
nxt =
if h == 0 do
[1]
else
digits = Integer.digits(h)
c = Enum.count(digits)
if rem(c, 2) == 0 do
{a, b} = Enum.split(digits, div(c, 2))
a = Integer.undigits(a)
b = Integer.undigits(b)
[a, b]
else
[h*2024]
end
end
{res, cache} = solve(nxt, rem-1, cache)
cache = Map.put(cache, key, res)
{res, cache}
end
end
defp solve([h | t], rem, cache) do
{c1, cache} = solve([h], rem, cache)
{c2, cache} = solve(t, rem, cache)
{c1 + c2, cache}
end
end
data = IO.read(:stdio, :eof)
{time1 , ans1} = :timer.tc(fn -> Day11.part1(data) end)
IO.puts("Time : #{time1 / 1000000}")
IO.puts("Answer: #{ans1}")
{time2 , ans2} = :timer.tc(fn -> Day11.part2(data) end)
IO.puts("Time : #{time2 / 1000000}")
IO.puts("Answer: #{ans2}")