136 lines
3.2 KiB
Elixir
136 lines
3.2 KiB
Elixir
defmodule Day15 do
|
|
def part1(example \\ false) do
|
|
find_number_spoken_at(example, 2020)
|
|
end
|
|
|
|
def part2(example \\ false) do
|
|
find_number_spoken_at(example, 30_000_000)
|
|
end
|
|
|
|
def find_number_spoken_at(example, final_turn) do
|
|
inputs = parse_input(example)
|
|
|
|
# inputs
|
|
# |> Enum.reverse()
|
|
# |> step_times(final_turn - length(inputs))
|
|
# |> List.first()
|
|
|
|
# numbers = parse_input(example)
|
|
|
|
inputs
|
|
|> Enum.with_index()
|
|
|> Enum.map(fn {e, i} -> {e, i + 1} end)
|
|
|> Map.new()
|
|
|> do_van_eck(List.last(inputs), length(inputs) + 1, final_turn)
|
|
|
|
# |> step_until_turn(final_turn, length(numbers) + 1)
|
|
# |> what_was_spoken_on_turn(final_turn)
|
|
end
|
|
|
|
def parse_input(example) do
|
|
case example do
|
|
1 -> "0,3,6"
|
|
2 -> "1,3,2"
|
|
3 -> "2,1,3"
|
|
4 -> "1,2,3"
|
|
5 -> "2,3,1"
|
|
6 -> "3,2,1"
|
|
7 -> "3,1,2"
|
|
_ -> "9,12,1,4,17,0,18"
|
|
end
|
|
|> String.split(",")
|
|
|> Enum.map(&String.to_integer/1)
|
|
end
|
|
|
|
def do_van_eck(_, prev, turn, count) when turn == count + 1 do
|
|
prev
|
|
end
|
|
|
|
def do_van_eck(map, prev, turn, count) do
|
|
# IO.inspect(map)
|
|
|
|
new_val =
|
|
if Map.has_key?(map, prev) do
|
|
turn - map[prev]
|
|
else
|
|
0
|
|
end
|
|
|
|
# IO.inspect(map)
|
|
IO.puts("turn: #{turn} \tprev: #{prev} \tnew: #{new_val}")
|
|
|
|
do_van_eck(Map.put(map, prev, turn - 1), new_val, turn + 1, count)
|
|
end
|
|
|
|
def step_van_eck([prev | rest] = sequence) do
|
|
next =
|
|
case Enum.find_index(rest, &(&1 == prev)) do
|
|
nil -> 0
|
|
index_in_rest -> index_in_rest + 1
|
|
end
|
|
|
|
[next | sequence]
|
|
end
|
|
|
|
def step_times(sequence, 0) do
|
|
sequence
|
|
end
|
|
|
|
def step_times(sequence, count) do
|
|
step_times(step_van_eck(sequence), count - 1)
|
|
end
|
|
|
|
# def step(map, turn) do
|
|
# # IO.puts("current turn: #{turn}")
|
|
|
|
# {prev_spoken, prev_spoken_on_turns} = what_was_spoken_on_turn(map, turn - 1)
|
|
|
|
# # IO.puts("prev spoken: #{prev_spoken}")
|
|
# # IO.puts("prev spoken on turns: #{inspect(prev_spoken_on_turns)}")
|
|
|
|
# number_to_speak =
|
|
# case prev_spoken_on_turns do
|
|
# [_] ->
|
|
# 0
|
|
|
|
# [most_recent, second_most_recent | _] ->
|
|
# most_recent - second_most_recent
|
|
# # List.last(prev_spoken_on_turns) - Enum.at(prev_spoken_on_turns, -2)
|
|
# end
|
|
|
|
# # IO.puts("will speak #{number_to_speak}")
|
|
|
|
# Map.update(map, number_to_speak, [turn], fn turns -> [turn | turns] end)
|
|
# end
|
|
|
|
# def step_until_turn(map, final_turn, turn) when final_turn + 1 == turn do
|
|
# map
|
|
# end
|
|
|
|
# def step_until_turn(map, final_turn, turn) do
|
|
# # IO.inspect(map)
|
|
# step_until_turn(step(map, turn), final_turn, turn + 1)
|
|
# end
|
|
|
|
# # def step(numbers, turn) do
|
|
# # # prev = Map.get(map, cur - 1)
|
|
# # {prev, prev_turn} = Enum.find(numbers, &(elem(&1, 1) == turn - 1))
|
|
|
|
# # IO.puts("turn #{turn}")
|
|
# # IO.puts("prev #{prev}")
|
|
|
|
# # new =
|
|
# # case Enum.find(numbers, &(elem(&1, 0) == prev)) |> IO.inspect() do
|
|
# # nil -> 0
|
|
# # {_, ^prev_turn} -> 0
|
|
# # {_, last_spoken_turn} -> turn - last_spoken_turn
|
|
# # end
|
|
|
|
# # # IO.inspect({prev, new})
|
|
# # IO.puts("speak #{new}")
|
|
|
|
# # [{new, turn} | Enum.reject(numbers, fn {n, _} -> n == new end)]
|
|
# # |> IO.inspect()
|
|
# # end
|
|
end
|