Алгоритм размера - PullRequest
       29

Алгоритм размера

3 голосов
/ 26 января 2009

Хорошо, вот небольшая проблема, на которую я бы хотел помочь.

У меня есть вид, и размер области просмотра будет зависеть от разрешения экрана пользователя. В окне просмотра должно быть N блоков, которые выстроены рядом друг с другом справа налево и занимают все горизонтальное пространство в окне просмотра. Теперь, если бы все поля могли быть одинакового размера, это было бы легко, просто разделите ширину области просмотра на N, и вы в отъезде.

Проблема в том, что каждый прямоугольник должен быть на 10% меньше, чем прямоугольник с левой стороны, поэтому, например, если область просмотра имеет ширину 271 пиксель и есть три прямоугольника, я вернусь [100, 90, 81]

Поэтому мне нужен алгоритм, который при передаче ширины области просмотра и количества горизонтальных блоков возвращает массив, содержащий ширину, необходимую каждому из блоков, чтобы заполнить ширину области просмотра и уменьшить каждую размер ящиков на 10%.

Ответы на любом ОО языке это круто. Хотелось бы получить некоторые идеи о том, как подойти к этому, и, возможно, посмотреть, кто может предложить самое элегантное решение.

С уважением,

Chris

Ответы [ 7 ]

4 голосов
/ 26 января 2009

Используя простую геометрическую прогрессию, в Python,

def box_sizes(width, num_boxes) :
    first_box = width / (10 * (1 - 0.9**n))
    return [first_box * 0.9**i for i in range(n)]

>>> box_sizes(100, 5)
[24.419428096993972, 21.977485287294574, 19.779736758565118, 17.801763082708607, 16.021586774437747]
>>> sum(_)
100.00000000000001

Возможно, вы захотите повысить точность или преобразовать в целые числа, но это должно быть сделано.

3 голосов
/ 26 января 2009

Это действительно математическая проблема. С двумя коробками дано:

x = размер первой коробки n = количество ящиков P = количество пикселей

тогда

x + 0,9x = P

3: x + 0,9x + 0,81x = P
4: x + 0,9x + 0,81x + 0,729x = P

, который фактически является геометрическим рядом в виде:

S (n) = a + ar + ar n + ... + ar n-1

где:

a = размер первой коробки
r = 0,9
S (n) = P

S (n) = a (1-r n ) / (1-r)

так

x = 0,1P / (1-0,9 n )

, что (наконец-то!) Кажется правильным и может быть решено для любого (P, n).

2 голосов
/ 26 января 2009

Это называется Geometric Progression, и на нем есть статья в Википедии . Формулы там тоже. Я полагаю, что Клетус допустил ошибку с его f (n). Исправлено. :)

1 голос
/ 26 января 2009
    public static int[] GetWidths(int width, int partsCount)
    {
        double q = 0.9;
        int[] result = new int[partsCount];

        double a = (width * (1 - q)) / (1 - Math.Pow(q, partsCount));

        result[0] = (int) Math.Round(a);
        int sum = result[0];

        for (int i = 1; i < partsCount - 1; i++)
        {
            result[i] = (int) Math.Round( a * Math.Pow(q, i) );
            sum += result[i];
        }

        result[partsCount - 1] = width - sum;

        return result;
    }

Это потому что это геометрическая прогрессия .

1 голос
/ 26 января 2009
Let:
x = size of the first box
n = number of boxes
P = number of pixels

n = 1: x = P
n = 2: x + .9x = P
n = 3: x + .9x + .81x = P

P = x sum[1..n](.9 ^ (n - 1))

Therefore:
x = P / sum[1..n](.9 ^ (n - 1))

Using the Geometric Progression formula:
x = P (.9 - 1) / ((.9 ^ n) - 1))

Test:
P = 100
n = 3
Gives:
x = 36.9
0 голосов
/ 26 января 2009

Как уже упоминалось, ширина полей образует геометрическую прогрессию . Учитывая ширину области просмотра W и количество блоков N , мы можем непосредственно определить для ширины самого широкого поля X . Для размещения N ящиков в окне просмотра нам нужно

X + 0,9 X + 0,9 ^ 2 X + ... + 0,9 ^ ( N -1) X <= <strong>Ш

{1 + 0,9 + 0,9 ^ 2 + ... + 0,9 ^ ( N -1)} X <= <strong>Ш

Применение формулы для суммы геометрической прогрессии дает

(1 - 0,9 ^ N ) X / (1 - 0,9) <= <strong>W

X <= 0,1 <strong>Ш / (1 - 0,9 ^ N )

Итак, у вас есть это выражение в закрытой форме, которое дает вам ширину самой широкой рамки X .

0 голосов
/ 26 января 2009

Начните с вычисления суммы значений ширины блоков, предполагая, что первый блок равен 1, второй - 0,81 и т. Д. Это можно сделать итеративно или из формулы для геометрических рядов. Затем масштабируйте каждый блок в соответствии с (шириной области просмотра) / (суммой ширины оригинальных блоков).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...