From c489f6e77ae9d8b56398fe9ca652ddc8f40b6dde Mon Sep 17 00:00:00 2001 From: Dustin Swan Date: Thu, 26 Dec 2024 20:48:14 -0700 Subject: [PATCH] Day 22 again. FINALLY. Just needed a map --- day22/main.exs | 96 +++++++++++--------------------------------------- 1 file changed, 21 insertions(+), 75 deletions(-) diff --git a/day22/main.exs b/day22/main.exs index b111b4d..bfdee2d 100644 --- a/day22/main.exs +++ b/day22/main.exs @@ -13,89 +13,44 @@ defmodule Day22 do 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} -> + # build a map of all 4-digit sequences + list index to prices + map = + Enum.with_index(lines) + |> Enum.reduce(%{}, fn {secret, idx}, map -> + {_, prices, diffs, map2} = + Enum.reduce(1..2000, {secret, [price(secret)], [], map}, fn _, {s, prices, diffs, m} -> new_secret = evolve(s) price = price(new_secret) diff = price - hd(prices) - {new_secret, [price | prices], [diff | diffs]} + new_diff = [diff | diffs] + sec = Enum.slice(new_diff, 0, 4) + new_map = Map.put_new(m, {sec, idx}, price) + {new_secret, [price | prices], new_diff, new_map} end) - {[prices | prices_acc], [diffs | diffs_acc]} - end) - - dbg({prices, diffs}) - - # max length of all price lists - max = Enum.map(prices, &length/1) |> Enum.max() - - # sort the lists by price, keeping their original index - sorted_by_price_with_index = - Enum.map(prices, fn prices -> - prices |> Enum.with_index() |> Enum.sort(fn {p1, _}, {p2, _} -> p1 >= p2 end) + map2 end) - |> Enum.with_index() - # dbg(sorted_by_price_with_index) + # for every possible sequence (there's only like 19 ^ 4 or something) + all = for a <- -9..9, b <- -9..9, c <- -9..9, d <- -9..9, do: [a, b, c, d] - # go from 0 up to the max list length of the lists sorted by price, highest to lowest - # grab the 4-sequence of each list - # check each sequence against each list, add up the prices - # if that price is greater than the max acc price, that's the new winning sequence part2 = - Enum.reduce(0..(max - 1), 0, fn index, acc -> - dbg({"checking all lists at index", index}) - dbg({"current acc", acc}) - - res = - Enum.reduce(sorted_by_price_with_index, {0, []}, fn {price_list, list_index}, - {max_price, max_seq} -> - {price, original_index} = Enum.at(price_list, index) - # dbg({diffs, index}) - seq = Enum.at(diffs, list_index) |> Enum.slice(original_index, 4) - # dbg({price, seq}) - - if length(seq) == 4 do - max_price = score_seq(prices, diffs, seq) - # dbg({"max_price", max_price}) - - {max_price, seq} - else - {max_price, max_seq} + Enum.reduce(all, {0, []}, fn sec, {max, max_sec} -> + # and for every buyer, get the price at this sequence + val = + Enum.reduce(0..length(lines), 0, fn idx, acc -> + case Map.get(map, {sec, idx}, nil) do + nil -> acc + val -> val + acc end end) - if res > acc do - dbg({"new high", res}) - res - else - acc - end + if val > max, do: {val, sec}, else: {max, max_sec} end) dbg(part2) end - defp score_seq(prices, diffs, seq) do - # dbg({"score seq", seq}) - - res = - Enum.zip(prices, diffs) - |> Enum.reduce(0, fn {p, d}, acc -> - case index_of_sublist(d, seq) do - nil -> acc - idx -> Enum.at(p, idx) + acc - end - end) - - res - # dbg(res) - end - defp evolve(secret) do step1 = secret |> Kernel.*(64) |> mix(secret) |> prune() step2 = step1 |> div(32) |> mix(step1) |> prune() @@ -113,15 +68,6 @@ defmodule Day22 do 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 - Enum.reduce_while(0..(length(parent) - length(sublist)), nil, fn idx, acc -> - if Enum.slice(parent, idx, length(sublist)) == sublist, - do: {:halt, idx}, - else: {:cont, acc} - end) - end end Day22.run()