views:

88

answers:

4

I need to find out a method to determine how many items should appear per column in a multiple column list to achieve the most visual balance. Here are my criteria:

  1. The list should only be split into multiple columns if the item count is greater than 10.
    • If multiple columns are required, they should contain no less than 5 (except for the last column in case of a remainder) and no more than 10 items.
  2. If all columns cannot contain an equal number of items
    • All but the last column should be equal in number.
    • The number of items in each column should be optimized to achieve the smallest difference between the last column and the other column(s).

Image showing two visual scenarios and suggested format

+4  A: 

Well, your requirements and your examples appear a bit contradictory. For instance, your second example could be divided into two columns with 11 items in each, and satisfy your criteria. Let's assume that for rule #2 you meant that there should be <= 10 items / column.

In addition, I think you need to add another rule to make the requirements sensible:

The number of columns must not be greater than what is required to accomodate overflow.

Otherwise, you will often end up with degenerate solutions where you have far more columns than you need. For example, in the case of 26 items you probably don't want 13 columns of 2 items each.

If that's case, here's a simple calculation that should work well and is easy to understand:

int numberOfColumns = CEILING(numberOfItems / 10);
int numberOfItemsPerColumn = CEILING(numberOfItems / numberOfColumns);

Now you'll create N-1 columns of items (having `numberOfItemsPerColumn each) and the overflow will go in the last column. By this definition, the overflow should be minimized in the last column.

LBushkin
I have edited my question a bit. You're correct that I actually meant "less than 10 items/column".
jessegavin
That works amazingly well. Thank you very much.
jessegavin
You're welcome.
LBushkin
I don't think this is the best solution. Say I have 77 items. The optimal solution is 11 columns of 7 items. LBushkin's solution gives you 8 columns, with ten in each except for the last which has 6.
Rafe
Sorry, pre-coffee arithmetic failure. The last column would have 7 items under this scheme.
Rafe
A: 

Here's what you're trying to solve:

minimize y - z where n = xy + z and 5 <= y <= 10 and 0 <= z <= y

where you have n items split into x full columns of y items and one remainder column of z items.

There is almost certainly a smart way of doing this, but given these constraints a brute force implementation exploring all 6 + 7 + 8 + 9 + 10 = 40 possible combinations for y and z would take no time at all (only assignments where (n - z) mod y = 0 are solutions).

Rafe
A: 

I think a brute force solution is easy, given the constraint on the number of items per columns: let v be the number of items per column (except the last one), then v belongs to [5,10] and can thus take a whooping 6 different values.

Evaluating 6 values is easy enough. Python one-liner (or not so far) to prove it:

# compute the difference between the number of items for the normal columns
# and for the last column, lesser is better
def helper(n,v):
  modulo = n % v
  if modulo == 0: return 0
  else: return v - modulo

# values can only be in [5,10]
# we compute the difference with the last column for each
# build a list of tuples (difference, - number of items)
# (because the greater the value the better, it means less columns)
# extract the min automatically (in case of equality, less is privileged)
# and then pick the number of items from the tuple and re-inverse it
def compute(n): return - min([(helper(n,v), -v) for v in [5,6,7,8,9,10]])[1]

For 77 this yields: 7 meaning 7 items per columns
For 22 this yields: 8 meaning 8 items per columns

Matthieu M.
A: 

If you want to automatically determine the appropriate number of columns, and have no restrictions on its limits, I would suggest the following:

  • Calculate the square root of the total number of items. That would make an squared layout.
  • Divide that number by 1.618, and assign that to the total number of rows.
  • Multiply that same number by 1.618, and assign that to the total number of columns.
  • All columns but the right most one will have the same number of items.

By the way, the constant 1.618 is the Golden Ratio. That will achieve a more pleasant layout than a squared one. Divide and multiply the other way round for vertical displays. Hope this algorithm helps anyone with a similar problem.

Manuel Gonzalez