88 lines
1.5 KiB
Elixir
88 lines
1.5 KiB
Elixir
defmodule Day15 do
|
|
defp read_input do
|
|
Path.expand('input', Path.dirname(__ENV__.file))
|
|
|> File.read!()
|
|
end
|
|
|
|
defp test_input do
|
|
"""
|
|
0,3,6
|
|
"""
|
|
end
|
|
|
|
defp parse_numbers(text) do
|
|
text
|
|
|> String.trim()
|
|
|> String.split(",")
|
|
|> Enum.map(&String.to_integer/1)
|
|
end
|
|
|
|
defp next([previous | rest]) do
|
|
{_, idx} =
|
|
rest
|
|
|> Enum.with_index()
|
|
|> Enum.find({previous, -1}, fn {num, _idx} -> num == previous end)
|
|
|
|
idx + 1
|
|
end
|
|
|
|
defp run(log, limit) do
|
|
if Enum.count(log) == limit do
|
|
Enum.at(log, 0)
|
|
else
|
|
run([next(log) | log], limit)
|
|
end
|
|
end
|
|
|
|
def part1(limit) do
|
|
read_input()
|
|
|> parse_numbers()
|
|
|> Enum.reverse()
|
|
|> run(limit)
|
|
end
|
|
|
|
defp setup(initial) do
|
|
cache =
|
|
initial
|
|
|> Enum.slice(0..-2)
|
|
|> Enum.with_index()
|
|
|> Enum.into(%{})
|
|
|
|
{cache, Enum.at(initial, -1)}
|
|
end
|
|
|
|
defp next2(cache, said, now) do
|
|
now - Map.get(cache, said, now)
|
|
end
|
|
|
|
defp run2(cache, said, now, stop) do
|
|
say = next2(cache, said, now)
|
|
|
|
if now + 1 == stop do
|
|
said
|
|
else
|
|
run2(Map.put(cache, said, now), say, now + 1, stop)
|
|
end
|
|
end
|
|
|
|
def part2(limit) do
|
|
{cache, said} =
|
|
read_input()
|
|
|> parse_numbers()
|
|
|> setup()
|
|
|
|
run2(cache, said, map_size(cache), limit)
|
|
end
|
|
|
|
def debug(limit) do
|
|
10..limit
|
|
|> Enum.filter(fn i ->
|
|
p1 = part1(i)
|
|
p2 = part2(i)
|
|
p1 != p2
|
|
end)
|
|
end
|
|
end
|
|
|
|
Day15.part1(2020) |> IO.inspect()
|
|
Day15.part2(30_000_000) |> IO.inspect()
|