Advertisement
Guest User

AoC 2024 Day 9 Part 2

a guest
Dec 12th, 2024
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 4.03 KB | Source Code | 0 0
  1. #! /usr/bin/env lua
  2.  
  3. function main()
  4.     local file_spans, free_spans = read_input()
  5.     local result = defragment_spans(file_spans, free_spans)
  6.     print(result)
  7. end
  8.  
  9. function defragment_spans(file_spans, free_spans)
  10.     local checksum = 0
  11.  
  12.     local impossible_sizes = { false, false, false, false, false, false, false, false, false }
  13.     local impossible_sizes_length = 0
  14.  
  15.     local last_file_span_index = 0
  16.     local file_spans_length = #file_spans
  17.     for file_span_index = file_spans_length, 1, -1 do
  18.         local file_span = file_spans[file_span_index]
  19.         local file_span_size = file_span.size
  20.         local file_span_start_block_index = 0
  21.  
  22.         local free_span = nil
  23.         local candidate_free_span = nil
  24.  
  25.         if (impossible_sizes[file_span_size]) then
  26.             goto continue
  27.         end
  28.  
  29.         file_span_start_block_index = file_span.start_block_index
  30.  
  31.         candidate_free_span = free_spans
  32.         while (candidate_free_span ~= nil) do
  33.             if (candidate_free_span.start_block_index >= file_span_start_block_index) then
  34.                 break
  35.             end
  36.  
  37.             if (candidate_free_span.size >= file_span_size) then
  38.                 free_span = candidate_free_span
  39.                 break
  40.             end
  41.  
  42.             candidate_free_span = candidate_free_span.next
  43.         end
  44.  
  45.         if (free_span == nil) then
  46.             impossible_sizes[file_span_size] = true
  47.  
  48.             impossible_sizes_length = impossible_sizes_length + 1
  49.             if (impossible_sizes_length == 9) then
  50.                 last_file_span_index = file_span_index
  51.                 break
  52.             end
  53.  
  54.             goto continue
  55.         end
  56.  
  57.         file_span.start_block_index = free_span.start_block_index
  58.  
  59.         new_free_span_size = free_span.size - file_span_size
  60.         if (new_free_span_size ~= 0) then
  61.             free_span.start_block_index = free_span.start_block_index + file_span_size
  62.             free_span.size = new_free_span_size
  63.         else
  64.             if (free_span == free_spans) then
  65.                 free_spans = free_span.next
  66.             end
  67.        
  68.             if (free_span.prev ~= nil) then
  69.                 free_span.prev.next = free_span.next
  70.             end
  71.  
  72.             if (free_span.next ~= nil) then
  73.                 free_span.next.prev = free_span.prev
  74.             end
  75.  
  76.             free_span.prev = nil
  77.             free_span.next = nil
  78.         end
  79.  
  80.         ::continue::
  81.  
  82.         checksum = checksum +
  83.             file_span.size * file_span.file_index * (file_span.start_block_index + ((file_span.size - 1) / 2))
  84.     end
  85.  
  86.     for file_span_index = last_file_span_index, 1, -1 do
  87.         local file_span = file_spans[file_span_index]
  88.         checksum = checksum +
  89.             file_span.size * file_span.file_index * (file_span.start_block_index + ((file_span.size - 1) / 2))
  90.     end
  91.  
  92.     return math.tointeger(checksum)
  93. end
  94.  
  95. function read_input()
  96.     local file_spans = {}
  97.     local free_spans = nil
  98.     local prev_free_span = nil
  99.  
  100.     local block_index = 0
  101.     local is_file_span = true
  102.     local file_index = 0
  103.     while (true) do
  104.         local input = io.read(1)
  105.         if (input == '\n') then
  106.             break
  107.         end
  108.  
  109.         local span = {
  110.             start_block_index = block_index,
  111.             size = tonumber(input)
  112.         }
  113.  
  114.         if (is_file_span) then
  115.             span.file_index = file_index
  116.             table.insert(file_spans, span)
  117.         else
  118.             span.next = nil
  119.  
  120.             if (free_spans == nil) then
  121.                 span.prev = nil
  122.                 free_spans = span
  123.             else
  124.                 span.prev = prev_free_span
  125.                 prev_free_span.next = span
  126.             end
  127.  
  128.             prev_free_span = span
  129.         end
  130.  
  131.         block_index = block_index + span.size
  132.  
  133.         if (is_file_span) then
  134.             is_file_span = false
  135.         else
  136.             is_file_span = true
  137.             file_index = file_index + 1
  138.         end
  139.     end
  140.  
  141.     return file_spans, free_spans
  142. end
  143.  
  144. main()
  145.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement