diff --git a/day22/main.exs b/day22/main.exs new file mode 100644 index 0000000..41cd0e9 --- /dev/null +++ b/day22/main.exs @@ -0,0 +1,131 @@ +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()