AoC20/lib/day15/day15.ex

136 lines
3.2 KiB
Elixir
Raw Normal View History

2020-12-16 22:43:05 +00:00
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