Day 22. This solution also does not scale. I think I\'ll try a map or something next

This commit is contained in:
Dustin Swan 2024-12-26 19:51:51 -07:00
parent 2a3ca7c393
commit 141e4761d3
No known key found for this signature in database
GPG key ID: AB49BD6B2B3A6377

View file

@ -1,7 +1,7 @@
defmodule Day22 do defmodule Day22 do
def run do def run do
lines = lines =
File.read!("test.txt") File.read!("data.txt")
|> String.trim() |> String.trim()
|> String.split("\n") |> String.split("\n")
|> Enum.map(&String.to_integer/1) |> Enum.map(&String.to_integer/1)
@ -28,70 +28,74 @@ defmodule Day22 do
{[prices | prices_acc], [diffs | diffs_acc]} {[prices | prices_acc], [diffs | diffs_acc]}
end) end)
dbg(prices) dbg({prices, diffs})
dbg(diffs)
concatted_diffs = Enum.concat(diffs) # max length of all price lists
max = Enum.map(prices, &length/1) |> Enum.max()
# iterate over ALL 4 diff sequences among all the numbers # sort the lists by price, keeping their original index
part2 = sorted_by_price_with_index =
concatted_diffs Enum.map(prices, fn prices ->
prices |> Enum.with_index() |> Enum.sort(fn {p1, _}, {p2, _} -> p1 >= p2 end)
end)
|> Enum.with_index() |> 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 # dbg(sorted_by_price_with_index)
# 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 # go from 0 up to the max list length of the lists sorted by price, highest to lowest
dbg("found seq") # grab the 4-sequence of each list
dbg(seq) # check each sequence against each list, add up the prices
dbg({"checking diff list for this seq", i}) # if that price is greater than the max acc price, that's the new winning sequence
end part2 =
Enum.reduce(0..(max - 1), 0, fn index, acc ->
dbg({"checking all lists at index", index})
dbg({"current acc", acc})
# if this seq exists in this diff list, find the corresponding price res =
if !is_nil(i) do Enum.reduce(sorted_by_price_with_index, {0, []}, fn {price_list, list_index},
# dbg(list_idx) {max_price, max_seq} ->
# dbg(prices) {price, original_index} = Enum.at(price_list, index)
price_list = Enum.at(prices, list_idx) # dbg({diffs, index})
# dbg(price_list) seq = Enum.at(diffs, list_index) |> Enum.slice(original_index, 4)
price = Enum.at(price_list, i) # dbg({price, seq})
if Enum.reverse(seq) == [-2, 1, -1, 3] do if length(seq) == 4 do
dbg({"price", price}) max_price = score_seq(prices, diffs, seq)
end # dbg({"max_price", max_price})
# dbg({"found the seq. price", price}) {max_price, seq}
acc + price else
else {max_price, max_seq}
acc end
end end)
end)
if Enum.reverse(seq) == [-2, 1, -1, 3] do if res > acc do
dbg({"total total", total}) dbg({"new high", res})
end res
if total >= max do
dbg({"new winner", total, seq})
{total, seq}
else
{max, best_seq}
end
else else
{max, best_seq} acc
end end
end) end)
dbg(part2) dbg(part2)
end 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 defp evolve(secret) do
step1 = secret |> Kernel.*(64) |> mix(secret) |> prune() step1 = secret |> Kernel.*(64) |> mix(secret) |> prune()
step2 = step1 |> div(32) |> mix(step1) |> prune() step2 = step1 |> div(32) |> mix(step1) |> prune()
@ -112,18 +116,10 @@ defmodule Day22 do
# finds the index of a sequence in a list, nil if it isn't in there # finds the index of a sequence in a list, nil if it isn't in there
defp index_of_sublist(parent, sublist) do defp index_of_sublist(parent, sublist) do
sub_len = length(sublist) Enum.reduce_while(0..(length(parent) - length(sublist)), nil, fn idx, acc ->
if Enum.slice(parent, idx, length(sublist)) == sublist,
Enum.reduce(0..(length(parent) - sub_len), nil, fn idx, acc -> do: {:halt, idx},
if acc do else: {:cont, acc}
acc
else
slice = Enum.slice(parent, idx, sub_len)
if slice == sublist do
idx
end
end
end) end)
end end
end end