Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env elixir
- argv = System.argv()
- if length(argv) != 1 do
- IO.puts(:stderr, "Usage: 2024/day-09/main.exs <file>")
- System.stop(64)
- end
- disk_map =
- argv |> hd() |> File.read!() |> String.trim() |> String.to_charlist() |> Enum.map(&(&1 - ?0))
- file_blocks = disk_map |> Enum.take_every(2)
- free_blocks = disk_map |> tl() |> Enum.take_every(2)
- file_count = file_blocks |> Enum.sum()
- blocks =
- Enum.zip(file_blocks, free_blocks)
- |> Enum.with_index()
- |> Enum.map(fn {{file_block, free_block}, i} ->
- List.duplicate(i, file_block) ++ List.duplicate(-1, free_block)
- end)
- |> Kernel.++([List.duplicate(length(file_blocks) - 1, Enum.at(file_blocks, -1))])
- |> List.flatten()
- neg_block_length = -length(blocks)
- checksum =
- blocks
- |> Enum.reduce_while({-1, []}, fn block, {last, list} ->
- if length(list) == file_count do
- {:halt, {last, list}}
- else
- cond do
- Enum.at(blocks, last) == -1 ->
- last =
- Enum.reduce_while(last..neg_block_length//-1, last, fn _, acc ->
- if Enum.at(blocks, acc) == -1 do
- {:cont, acc - 1}
- else
- {:halt, acc}
- end
- end)
- if block == -1 do
- {:cont, {last - 1, Enum.concat(list, [Enum.at(blocks, last)])}}
- else
- {:cont, {last, Enum.concat(list, [block])}}
- end
- block == -1 ->
- {:cont, {last - 1, Enum.concat(list, [Enum.at(blocks, last)])}}
- true ->
- {:cont, {last, Enum.concat(list, [block])}}
- end
- end
- end)
- |> elem(1)
- |> Enum.with_index()
- |> Enum.sum_by(fn {block, i} -> block * i end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement