5

I have a list of rectangles with different dimensions.

rects = [100x20, 30x10, 10x10, 70x20, 40x30, 50x10]

I am trying to render a table from these rectangles. If I would have a fix number of columns, I simply could calculate the number of rows and the size of each row and column like this:

numCols = 4;

for (i = 0; i < rects.size - 1, i++):
    rect = rects[i];
    col = i % numCols;
    row = floor(i / numCols);

    columns[col] = max(columns[col], rect.width);
    rows[row] = max(rows[row], rect.height);
end for;

Now I want my table to be configured by a max row width. The number of columns depends on a runtime calculation of the optimal row width.

With the list above and a max row with set to 140 I expect my table to be:

rects = [100x20, 30x10, 70x10, 10x20, 40x30, 10x10]

100x20, 30x10
70x10, 10x20
40x30, 10x10

cols = [100, 30]
rows = [20, 20, 30]

My first idea to approach the situation is to cache the max column width for each possible number of colums. The last entry with a sum <= max row width then wins.

max[1] = [100]
max[2] = [100, 30] - wins
max[3] = [100, 40, 70] - 210 > 140
max[4] = [100, 30, 70, 10]
max[5] = [100, 30, 70, 10, 40]
max[6] = [100, 30, 70, 10, 40, 10]

Unfortunately, I need to create an entry in max for each possible column number. The list can get pretty big. Does someone know an algorithm to solve this optimization problem?

Kaken Bok
  • 3,395
  • 1
  • 19
  • 21
  • Maybe you can add a little more detail about the problem your algorithm should solve. What exactly do you want to optimize (number of rows, height of table)? E.g. your approach gives max[2]=[100,10] while your example it is [100,30]. Why do you prefer the first? In your examples you do never change order of rectangles. Is this a requirement? Also the title states "evenly sized" but you never mention this in the description. I suppose we can find a (known) algorithm if we knew more about the objective. – Howard Mar 02 '11 at 18:15
  • How big is 'pretty big' for the max array? It seems like a sensible approach, greedily take the widest rectangles and put then in the columns starting from the left (the widest rectangle has to go somewhere, and you may as well use as much of the space under it as possible). You don't have to store the array of max, just the best so far, and it's trivial to calculate the row width for a given number of columns (if you just sort the rectangles in order of decreasing width, it's a quick loop and add). If I understand the problem correctly, I'll move this to an answer. – Chris Nash Mar 02 '11 at 20:13
  • @Howard, your are right with max[2] = [100, 30]. I have updated the example. – Kaken Bok Mar 02 '11 at 21:28
  • To imagine the problem, take a list of thumbnails of different sizes to be displayed in a table that has only a max width given but no number of columns/rows. The order of thumnails is important. The height of the table is infinite but the optimal solution produces the most minimal number of rows. – Kaken Bok Mar 02 '11 at 21:34
  • @Howard, "evenly sized" just means that cells within one column should have the same width. Items may be smaller than their enclosing cell. – Kaken Bok Mar 03 '11 at 05:29

2 Answers2

1

I can see only optimizations to your solution:

Assumptions:
MaxAllowedWidth - maximum allowed sum of all columns width

  1. When looking for possible solutions (your last table) stop trying to add new columns when total column width will exceed MaxAllowedWidth. In your sample you should stop on third step and do not try 4, 5, 6 columns because 3 columns already will take more space that you're allowed to. Please note that on this step we're taking into account only first row of items.

  2. Go through possible columns number received in previous step in reverse order. First applicable solution will be optimal since it will have minimum possible number of rows.

  3. On step 2 you should check that this number of columns will really fit into your MaxAllowedWidth. In your sample you will start with total width = 130 (100 + 30). Then going through the columns you should check whether this specific column should be enlarged. If column should be enlarged then check whether enlarged column will take more space than you have left. If it will then try solution with less columns. This checks will allow you to exit earlier and skip useless iterations/operations.

The question description is not that clear, I didn't got what do you want till I read comments. max row width makes no sense to me, total columns width sounds better, IMO.

Snowbear
  • 16,924
  • 3
  • 43
  • 67
  • Spasibo Snowbear! The possible number of columns can be ranged like this: Adding the widest items till `MaxAllowedWidth` is reached gives the minimum number of columns that fits. Then taking the widest and adding the lowest items till `MaxAllowedWidth` is reached gives the maximum number of columns possible. Giving a shuffled list of the widths 1, ..., 100 and a `MaxAllowedWidth` of 300, the possible number of columns ranges from 4 to 20 whereas 3 (100+99+98 < 300) will fit. – Kaken Bok Mar 03 '11 at 15:43
  • I do not think you even need to think about `minimum` number of columns. Because in this task it may happen that some number of columns will not fit, but putting into **more** columns will help. The example is rects: [1, 1, 100, 1, 1, 100] with `maxAllowedWidth=150`. In this case 2 columns won't fit since they both should have `100` width, but three columns will fit because two biggest items will got into the same column. So I do not think you have to worry about minimum number of columns. – Snowbear Mar 03 '11 at 15:58
  • The min number is the break point if no other possibility is satisfying. – Kaken Bok Mar 03 '11 at 16:57
  • Well, next insight: Creating the table is an overhead. It is anyway cheaper to calculate the max column width at runtime and on demand. The optimization goes now in the direction to limit the maximum possible number of columns. What heuristic could help? Measuring the items right next to the widest one could give a better prediction than considering the most minimal items as said above: [1,1,1,100,1,100,1,1,1] and `maxAllowedWidth=150` using the first '100' will give a max of 2 columns (100+1). The minimum approach instead returns (100+1+1+1+1+1+1+1) 8 columns. – Kaken Bok Mar 03 '11 at 17:15
  • @Jens, if you are not allowed to reorder items (as you said) then one way to calculate maximum number of columns will be to take items while their total width is less then `MaxAllowedWidth`. In this your sample it will take until second `100` element will be found. – Snowbear Mar 03 '11 at 17:41
0

To complete this question, here the resulting table layout in action. You may set a max width, the number of columns is calculated based on the algorithm discussed in this thread:

http://sibirjak.com/osflash/projects/as3commons-ui/layouts/showcase/#a6-dyntable

Edit:

To modify the number of boxes, please open the boxes window from the task bar at the bottom of the example flash window.

Kaken Bok
  • 3,395
  • 1
  • 19
  • 21