[2024][ruby][9.2]
change mrqznxnxxumumxloosrxpqzzovlsnkrm
commit 8744fd7df7f0207447f3ecc4d12ea8c4e2c1e7c4
author Alpha Chen <alpha@kejadlen.dev>
date
parent pmktmrnq
diff --git a/2024/ruby/day_09.rb b/2024/ruby/day_09.rb
index a1053ad..dcca30e 100644
--- a/2024/ruby/day_09.rb
+++ b/2024/ruby/day_09.rb
@@ -3,19 +3,70 @@ disk_map = DATA.read.chars.each_slice(2)
     [ Array.new(a.to_i, i), Array.new(b.to_i, nil) ]
   }.reject(&:empty?)
 
-while (prev, free = disk_map.each_cons(2).find { _2.include?(nil) })
-  tail = disk_map.last
-  until free.empty? || tail.empty?
-    prev << tail.shift
-    free.pop
+# while (prev, free = disk_map.each_cons(2).find { _2.include?(nil) })
+#   tail = disk_map.last
+#   until free.empty? || tail.empty?
+#     prev << tail.shift
+#     free.pop
+#   end
+#
+#   while disk_map.last.all?(&:nil?)
+#     disk_map.pop
+#   end
+# end
+
+# pp disk_map.flatten.compact.each.with_index.sum { _1 * _2 }
+
+Block = Struct.new(:id, :size, :prev, :next) do
+  def each
+    return enum_for(__method__) unless block_given?
+
+    cur = self
+    while cur
+      yield cur
+      cur = cur.next
+    end
+  end
+
+  def inspect
+    "<Block id=#{id} size=#{size} prev=#{prev&.id} next=#{self.next&.id}>"
+  end
+
+  def to_s
+    (id || ?.).to_s * size
   end
+end
+
+blocks = disk_map.map { Block.new(_1[0], _1.size) }
+  .each_cons(2) { _1.next = _2; _2.prev = _1 }
 
-  while disk_map.last.all?(&:nil?)
-    disk_map.pop
+head = blocks.first
+tail = blocks.last
+
+until tail == head
+  unless tail.id.nil?
+    find_free = head
+    until (find_free.id.nil? && find_free.size >= tail.size) || (find_free == tail)
+      find_free = find_free.next
+    end
+    if find_free != tail
+      a = find_free
+      b = tail
+      a.id, b.id = b.id, a.id
+
+      if a.size > b.size
+        c = Block.new(nil, a.size - b.size, a, a.next)
+        a.size = b.size
+        a.next = c
+        c.next.prev = c
+      end
+    end
   end
+
+  tail = tail.prev
 end
 
-pp disk_map.flatten.each.with_index.sum { _1 * _2 }
+pp head.each.flat_map { Array.new(_1.size, _1.id) }.each.with_index.sum { _1.to_i * _2 }
 
 __END__
 2333133121414131402