defmodule Day22 do def run do lines = File.read!("test.txt") |> String.trim() |> String.split("\n") |> Enum.map(&String.to_integer/1) part1 = Enum.reduce(lines, 0, fn secret, acc -> acc + Enum.reduce(1..2000, secret, fn _, s -> evolve(s) end) end) dbg(part1) # lines = [123, 123] {prices, diffs} = Enum.reduce(lines, {[], []}, fn secret, {prices_acc, diffs_acc} -> {_, prices, diffs} = Enum.reduce(1..2000, {secret, [price(secret)], []}, fn _, {s, prices, diffs} -> new_secret = evolve(s) price = price(new_secret) diff = price - hd(prices) {new_secret, [price | prices], [diff | diffs]} end) {[prices | prices_acc], [diffs | diffs_acc]} end) dbg(prices) dbg(diffs) concatted_diffs = Enum.concat(diffs) # iterate over ALL 4 diff sequences among all the numbers part2 = concatted_diffs |> Enum.with_index() |> Enum.reduce({0, []}, fn {d, idx}, {max, best_seq} -> seq = Enum.slice(concatted_diffs, idx, 4) # dbg({d, idx, seq}) if length(seq) == 4 do # find the index of this 4 diff sequence in all the diff lists total = Enum.with_index(diffs) |> Enum.reduce(0, fn {diff_list, list_idx}, acc -> i = index_of_sublist(diff_list, seq) # dbg({"looking for sublist", seq, i}) if Enum.reverse(seq) == [-2, 1, -1, 3] do dbg("found seq") dbg(seq) dbg({"checking diff list for this seq", i}) end # if this seq exists in this diff list, find the corresponding price if !is_nil(i) do # dbg(list_idx) # dbg(prices) price_list = Enum.at(prices, list_idx) # dbg(price_list) price = Enum.at(price_list, i) if Enum.reverse(seq) == [-2, 1, -1, 3] do dbg({"price", price}) end # dbg({"found the seq. price", price}) acc + price else acc end end) if Enum.reverse(seq) == [-2, 1, -1, 3] do dbg({"total total", total}) end if total >= max do dbg({"new winner", total, seq}) {total, seq} else {max, best_seq} end else {max, best_seq} end end) dbg(part2) end defp evolve(secret) do step1 = secret |> Kernel.*(64) |> mix(secret) |> prune() step2 = step1 |> div(32) |> mix(step1) |> prune() step2 |> Kernel.*(2048) |> mix(step2) |> prune() end defp mix(num, secret) do Bitwise.bxor(num, secret) end defp prune(num) do Integer.mod(num, 16_777_216) end defp price(num) do Integer.digits(num) |> Enum.take(-1) |> Integer.undigits() end # finds the index of a sequence in a list, nil if it isn't in there defp index_of_sublist(parent, sublist) do sub_len = length(sublist) Enum.reduce(0..(length(parent) - sub_len), nil, fn idx, acc -> if acc do acc else slice = Enum.slice(parent, idx, sub_len) if slice == sublist do idx end end end) end end Day22.run()