tags:

views:

387

answers:

6

I'm looking for an algorithm that will evenly distribute 1 to many items into three columns. No column can have more than one more item than any other column. I typed up an example of what I'm looking for below. Adding up Col1,Col2, and Col3 should equal ItemCount.

Edit: Also, the items are alpha-numeric and must be ordered within the column. The last item in the column has to be less than the first item in the next column.

Items         Col1,Col2,Col3
A             A
AB            A,B
ABC           A,B,C
ABCD          AB,C,D
ABCDE         AB,CD,E
ABCDEF        AB,CD,EF
ABCDEFG       ABC,DE,FG
ABCDEFGH      ABC,DEF,GH
ABCDEFGHI     ABC,DEF,GHI
ABCDEFHGIJ    ABCD,EFG,HIJ
ABCDEFHGIJK   ABCD,EFGH,IJK
+2  A: 

This answer is now obsolete because the OP decided to simply change the question after I answered it. I’m just too lazy to delete it.

function getColumnItemCount(int items, int column) {
    return (int) (items / 3) + (((items % 3) >= (column + 1)) ? 1 : 0);
}
Bombe
This was useful once I figured out that "column" is expected to be counted from 0, as opposed to the ordinal column number. :D
crunchyt
+3  A: 

just to give you a hint (it's pretty easy, so figure out yourself)

divide ItemCount by 3, rounding down. This is what is at least in every column.

Now you do ItemCount % 3 (modulo), which is either 1 or 2 (because else it would be dividable by 3, right) and you distribute that.

Johannes Rudolph
+1  A: 

Do you just want the count of items in each column? If you have n items, then the counts will be:

round(n/3), round(n/3), n-2*round(n/3)

where "round" round to the nearest integer (e.g. round(x)=(int)(x+0.5))

If you want to actually put the items there, try something like this Python-style pseudocode:

def columnize(items):
  i=0
  answer=[ [], [], [] ]
  for it in items:
    answer[i%3] += it
    i += 1
  return answer
redtuna
Your first line of code distributes 10 as (3,3,4), and 11 as (4,4,3).
Steve Jessop
You're right, it does. These numbers sum up correctly, though. The solution matches the requirements as I read them: no column has more than one more item than any other column. If you want the values to reflect the counts you'd get from the second code block, then I think you can use RichieHindle's code above.
redtuna
Fair enough - the spec has changed since then anyway.
Steve Jessop
+2  A: 

It's quite simple

If you have N elements indexed from 0 to N-1 and column indexed from 0to 2, the i-th element will go in column i mod 3 (where mod is the modulo operator, % in C,C++ and some other languages)

ThibThib
After reading your response I thought, "huh that was easy why didn't I think of that." and then I realized there was more to the question. See the edit.
Brian Bolton
+4  A: 

Here you go, in Python:

NumCols = 3
DATA = "ABCDEFGHIJK"

for ItemCount in range(1, 12):
    subdata = DATA[:ItemCount]

    Col1Count = (ItemCount + NumCols - 1) / NumCols
    Col2Count = (ItemCount + NumCols - 2) / NumCols
    Col3Count = (ItemCount + NumCols - 3) / NumCols

    Col1 = subdata[:Col1Count]
    Col2 = subdata[Col1Count:Col1Count+Col2Count]
    Col3 = subdata[Col1Count+Col2Count:]

    print "%2d   %5s  %5s  %5s" % (ItemCount, Col1, Col2, Col3)

# Prints:
#  1       A              
#  2       A      B       
#  3       A      B      C
#  4      AB      C      D
#  5      AB     CD      E
#  6      AB     CD     EF
#  7     ABC     DE     FG
#  8     ABC    DEF     GH
#  9     ABC    DEF    GHI
# 10    ABCD    EFG    HIJ
# 11    ABCD   EFGH    IJK
RichieHindle
Sorry for not getting the question clear the first time. I think your answer does the trick. I can first sort the items using any algorithm, and then use yours to figure out how many items should be in each column.Again sorry for not being clear on the question.
Brian Bolton
@Brian: No problem. Now updated to answer your updated question.
RichieHindle
A: 

Here's a PHP version I hacked together for all the PHP hacks out there like me (yup, guilt by association!)

function column_item_count($items, $column, $maxcolumns) {
    return round($items / $maxcolumns) + (($items % $maxcolumns) >= $column ? 1 : 0);
}

And you can call it like this...

$cnt = sizeof($an_array_of_data);
$col1_cnt = column_item_count($cnt,1,3);
$col2_cnt = column_item_count($cnt,2,3);
$col3_cnt = column_item_count($cnt,3,3);

Credit for this should go to @Bombe who provided it in Java (?) above.

NB: This function expects you to pass in an ordinal column number, i.e. first col = 1, second col = 2, etc...

crunchyt