Джейми, я интерпретировал «оптимальное количество строк и столбцов» как «сколько строк и столбцов будет иметь самые большие прямоугольники, соответствующие требуемым пропорциям и размеру экрана». Вот простой подход к этой интерпретации.
Каждый возможный выбор (количество строк и столбцов прямоугольников) приводит к максимально возможному размеру прямоугольника для указанных пропорций. Цикл возможных вариантов и вычисление результирующего размера реализует простой линейный поиск по пространству возможных решений. Вот фрагмент кода, который делает это, используя пример экрана 480 x 640 и прямоугольников в пропорции 3 x 5.
def min (a, b)
a < b ? a : b
end
screenh, screenw = 480, 640
recth, rectw = 3.0, 5.0
ratio = recth / rectw
puts ratio
nrect = 14
(1..nrect).each do |nhigh|
nwide = ((nrect + nhigh - 1) / nhigh).truncate
maxh, maxw = (screenh / nhigh).truncate, (screenw / nwide).truncate
relh, relw = (maxw * ratio).truncate, (maxh / ratio).truncate
acth, actw = min(maxh, relh), min(maxw, relw)
area = acth * actw
puts ([nhigh, nwide, maxh, maxw, relh, relw, acth, actw, area].join("\t"))
end
Запуск этого кода обеспечивает следующую трассировку:
1 14 480 45 27 800 27 45 1215
2 7 240 91 54 400 54 91 4914
3 5 160 128 76 266 76 128 9728
4 4 120 160 96 200 96 160 15360
5 3 96 213 127 160 96 160 15360
6 3 80 213 127 133 80 133 10640
7 2 68 320 192 113 68 113 7684
8 2 60 320 192 100 60 100 6000
9 2 53 320 192 88 53 88 4664
10 2 48 320 192 80 48 80 3840
11 2 43 320 192 71 43 71 3053
12 2 40 320 192 66 40 66 2640
13 2 36 320 192 60 36 60 2160
14 1 34 640 384 56 34 56 1904
Из этого ясно, что макет 4х4 или 5х3 будет давать самые большие прямоугольники. Также ясно, что размер прямоугольника (как функция числа строк) является наихудшим (наименьшим) в крайних значениях и наилучшим (наибольшим) в промежуточной точке. Предполагая, что количество прямоугольников является скромным, вы можете просто закодировать приведенные выше вычисления на выбранном вами языке, но выручить, как только результирующая область начнет уменьшаться после поднятия до максимума.
Это быстрое и грязное (но, надеюсь, довольно очевидное) решение. Если количество прямоугольников стало достаточно большим, чтобы беспокоить, вы можете настроить производительность различными способами:
- использовать более сложный алгоритм поиска (разделить пространство и рекурсивно искать лучший сегмент),
- если количество прямоугольников растет во время выполнения программы, сохраните предыдущий результат и ищите только близлежащие решения,
- примените немного исчисления, чтобы получить более быструю, точную, но менее очевидную формулу.