2024 Day 9 part 2 (inefficient)

This commit is contained in:
Adam Millerchip 2024-12-10 13:49:03 +09:00
parent 9d60658882
commit ae3695c161

View file

@ -27,11 +27,50 @@ defmodule Day9 do
|> elem(0)
end
# Wrote a crazy long implementation, but was fatally flawed because it didn't consider that
# moving a block needs to leave contiguous spaces behind if there were spaces on either side.
# Maybe can store the spaces as ranges, then merge the ranges?
def part2(_input) do
:ok
# Super inefficient, but this is the 2nd attempt after trying to be more efficient
# worked on the sample but not the actual input
def part2(input) do
{_, _, _, disk, files} =
Enum.reduce(input, {0, 0, true, %{}, []}, fn len, {idx, id, file?, disk, files} ->
if file? do
disk = Map.put(disk, idx, {:file, id, len})
files = [{idx, id, len} | files]
{idx + len, id + 1, not file?, disk, files}
else
disk = Map.put(disk, idx, {:space, len})
{idx + len, id, not file?, disk, files}
end
end)
Enum.reduce(files, disk, fn {idx, id, len}, disk ->
# This scans the disk every time. Could possibly optimise by storing the known
# eligible spaces separately
case Enum.find(0..(idx - 1), &match?({:space, gap} when gap >= len, disk[&1])) do
nil ->
disk
space_idx ->
{:space, spaces} = Map.fetch!(disk, space_idx)
disk = disk |> Map.delete(idx) |> Map.put(space_idx, {:file, id, len})
remainder_spaces = spaces - len
if remainder_spaces > 0 do
Map.put(disk, space_idx + len, {:space, remainder_spaces})
else
disk
end
end
end)
|> Enum.reduce(0, fn
{_idx, {:space, _}}, checksum ->
checksum
{idx, {:file, id, len}}, checksum ->
for idx <- idx..(idx + len - 1), reduce: checksum do
checksum -> checksum + idx * id
end
end)
end
def input do