サイズ (幅と高さ) が異なる多数の「レンガ」と、固定サイズのコンテナーがあります。コンテナ内のレンガを上から下に向かってできるだけコンパクトに配置したいと考えています。前のステップを考慮して、どのステップでもグリッドが最適であるべき基準を選択しました。これまでのところ、動作しない次の (非効率的な) コードがあります。
def fits?(x, y, w, h)
!((x + w > W) || (y + h > H))
end
def overlaps?(existing, modified)
existing[:x] + existing[:w] > modified[:x] && existing[:y] + existing[:h] > modified[:y] && modified[:x] + modified[:w] > existing[:x] && modified[:y] + modified[:h] > modified[:y]
end
AXIS = :x
W = 800
H = 6400
sizes = [
{ w: 200 , h: 200 },
{ w: 200 , h: 200 },
{ w: 400 , h: 400 },
{ w: 200 , h: 200 },
{ w: 200 , h: 200 },
{ w: 400 , h: 400 },
{ w: 600 , h: 600 },
{ w: 200 , h: 200 },
{ w: 800 , h: 800 },
]
existing = []
sizes.each do |size|
size[:x] = 0
size[:y] = 0
existing.each do |existing|
if overlaps?(size, existing)
if fits?(x = existing[:x] + existing[:w], y = existing[:y], size[:w], size[:h])
size[:x] = x
size[:y] = y
redo
end
if fits?(x = existing[:x], y = existing[:y] + existing[:h], size[:w], size[:h])
size[:x] = x
size[:y] = y
redo
end
case AXIS
when :x then size[:x] = 0; size[:y] = existing[:y] + existing[:h]
when :y then size[:y] = 0; size[:x] = existing[:x] + existing[:w]
end
end
end
puts "#{size[:x]} , #{size[:y]} , #{size[:w]} , #{size[:h]}"
existing << size
end
これを修正する方法はありますか?これは貪欲なアルゴリズムの代表的な例のようですが、どうあるべきかわかりません。