Advertisement
harbingeroftheend

Untitled

Dec 28th, 2024
1,299
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 1.68 KB | Source Code | 0 0
  1. #!/usr/bin/env elixir
  2.  
  3. argv = System.argv()
  4.  
  5. if length(argv) != 1 do
  6.   IO.puts(:stderr, "Usage: 2024/day-09/main.exs <file>")
  7.   System.stop(64)
  8. end
  9.  
  10. disk_map =
  11.   argv |> hd() |> File.read!() |> String.trim() |> String.to_charlist() |> Enum.map(&(&1 - ?0))
  12.  
  13. file_blocks = disk_map |> Enum.take_every(2)
  14. free_blocks = disk_map |> tl() |> Enum.take_every(2)
  15.  
  16. file_count = file_blocks |> Enum.sum()
  17.  
  18. blocks =
  19.   Enum.zip(file_blocks, free_blocks)
  20.   |> Enum.with_index()
  21.   |> Enum.map(fn {{file_block, free_block}, i} ->
  22.     List.duplicate(i, file_block) ++ List.duplicate(-1, free_block)
  23.   end)
  24.   |> Kernel.++([List.duplicate(length(file_blocks) - 1, Enum.at(file_blocks, -1))])
  25.   |> List.flatten()
  26.  
  27. neg_block_length = -length(blocks)
  28.  
  29. checksum =
  30.   blocks
  31.   |> Enum.reduce_while({-1, []}, fn block, {last, list} ->
  32.     if length(list) == file_count do
  33.       {:halt, {last, list}}
  34.     else
  35.       cond do
  36.         Enum.at(blocks, last) == -1 ->
  37.           last =
  38.             Enum.reduce_while(last..neg_block_length//-1, last, fn _, acc ->
  39.               if Enum.at(blocks, acc) == -1 do
  40.                 {:cont, acc - 1}
  41.               else
  42.                 {:halt, acc}
  43.               end
  44.             end)
  45.  
  46.           if block == -1 do
  47.             {:cont, {last - 1, Enum.concat(list, [Enum.at(blocks, last)])}}
  48.           else
  49.             {:cont, {last, Enum.concat(list, [block])}}
  50.           end
  51.  
  52.         block == -1 ->
  53.           {:cont, {last - 1, Enum.concat(list, [Enum.at(blocks, last)])}}
  54.  
  55.         true ->
  56.           {:cont, {last, Enum.concat(list, [block])}}
  57.       end
  58.     end
  59.   end)
  60.   |> elem(1)
  61.   |> Enum.with_index()
  62.   |> Enum.sum_by(fn {block, i} -> block * i end)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement