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