d11
Section
ExUnit.start()
defmodule D11 do
def parse(input) do
String.split(input)
|> Enum.map(&String.to_integer/1)
end
def start_link do
if :ets.whereis(:memo_table) == :undefined do
:ets.new(:memo_table, [:set, :public, :named_table])
else
:ok
end
end
def evolve(stone, n) do
case :ets.lookup(:memo_table, {stone, n}) do
[] ->
result = D11.evolve_calc(stone, n)
:ets.insert(:memo_table, {{stone, n}, result})
result
[{_, result}] ->
result
end
end
def evolve_calc(_, 0), do: 1
def evolve_calc(stone, n) do
cond do
stone == 0 ->
D11.evolve(1, n - 1)
rem(String.length("#{stone}"), 2) == 0 ->
{x, y} = String.split_at("#{stone}", div(String.length("#{stone}"), 2))
D11.evolve(String.to_integer(x), n - 1) +
D11.evolve(String.to_integer(y), n - 1)
true ->
D11.evolve(stone * 2024, n - 1)
end
end
def part1(parsed) do
parsed
|> Enum.map(&D11.evolve(&1, 25))
|> Enum.sum()
end
def part2(parsed) do
parsed
|> Enum.map(&D11.evolve(&1, 75))
|> Enum.sum()
end
use ExUnit.Case
test "sample" do
assert 7 ==
D11.parse("0 1 10 99 999")
|> Enum.map(&D11.evolve(&1, 1))
|> Enum.sum()
assert 55312 == D11.part1([125, 17])
end
end
D11.start_link()
ExUnit.run()
input = File.read!(__DIR__ <> "/input")
parsed = D11.parse(input)
D11.part1(parsed)
D11.part2(parsed)