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