tags:

views:

157

answers:

4

I have a list of n logos to display in a grid, with a maximum of 3 per row. What's an algorithm to decide how many to display per row such that the number of logos per row is as balanced as possible without using more than the minimum possible number of rows?

For example:

 n -> number in each row
 1 -> 1
 2 -> 2
 3 -> 3
 4 -> 2, 2
 5 -> 3, 2
 6 -> 3, 3
 7 -> 3, 2, 2
 8 -> 3, 3, 2
 9 -> 3, 3, 3
10 -> 3, 3, 2, 2
+10  A: 
  • For N <= 3 just use N.
  • If N is exactly divisible by 3 then use: 3 3 ... 3
  • If N when divided by 3 has remainder 1 then use: 3 3 ... 2 2
  • If N when divided by 3 has remainder 2 then use: 3 3 ... 3 2
Mark Byers
missed special case N=1
Heath Hunnicutt
@Heath: Thanks, fixed.
Mark Byers
How can you use `3 3 ... 2 2` for `4`? Won't this print `3 1` for `4`?
IVlad
@IVlad: (4 % 3) == 1 so use 3 3 .. 2 2. Since 2 + 2 = 4, you need no 3's and two 2's.
Mark Byers
+5  A: 

AS confusing as your question is, I think what you need to do is first determine:

number_of_rows = ceil(number_of_logos / 3.0)

Then add a logo to each row, one at a time.

Python:

import math
def partition_logos(count, lsize):
    num_lines = int(math.ceil(count / float(lsize)))
    partition = [0] * num_lines
    for i in xrange(count):
        partition[i%num_lines] += 1
    return partition

>>> for i in xrange(1,11):
...     print partition_logos(i, 3)
[1]
[2]
[3]
[2, 2]
[3, 2]
[3, 3]
[3, 2, 2]
[3, 3, 2]
[3, 3, 3]
[3, 3, 2, 2]
MikeyB
+1 - very simple :)
Mark Byers
Another good feature of this solution is that the 3 isn't hard-coded.
Mark Byers
Thanks. Isn't part of a programmer's job taking ambiguous, poorly specified requirements and distilling them down into a neat, tidy solution? ;)
MikeyB
+1  A: 

just use n/3 to calculate the row and n%3 to calculate the column

edit: ok i saw you edited your question.... i din't saw that you want to display 2 in each row if the are 4 logos. but then you can use n mod 3 to calculate if their is a reminder as others already suggested

if n%3 = 0 then just put 3 logos in each row if n%3 = 1 then put the last 4 logos in two rows if n%3 = 2 then put 3 logos in n row and the last 2 logos in a separate row

Roflcoptr
That would give 3 3 3 1 for 10, where the questioner wants 3 3 2 2 (i.e. try to balance the rows better).
psmears
yes i was still editing sry ;)
Roflcoptr
A: 

A recursive solution, in Python:

def logos_by_row(N, rows):
    width = 0
    if N > 4 or N == 3:
        width = 3
    elif N == 4 or N == 2:
        width = 2
    elif N == 1:
        width = 1

    if width != 0:
        rows.append(width)
        logos_by_row(N - width, rows)


answer = []
for i in range(10):
    logos_by_row(i+1, answer)
print answer
Heath Hunnicutt