2009-08-07 51 views
4

我正在寻找一种将1到多个项目均匀分布到三列中的算法。没有列可以有多于一个项目比任何其他列。我在下面打出了一个我正在寻找的例子。将Col1,Col2和Col3相加应该等于ItemCount。将项目均匀分配到3列的算法

编辑:此外,这些项目是字母数字,必须在列中排序。列中的最后一项必须小于下一列中的第一项。

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 
+8

@Brian:请花一点时间第一次发布正确的问题。七个人花了大量的精力回答你的问题的第一个版本,现在已经改变了,所以大部分工作都被浪费了。 – RichieHindle 2009-08-07 12:15:36

+0

ABCD的分布是A | BC | D还是A | B | CD? – christopheml 2009-08-07 12:17:31

回答

11

在这里你去,在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 
+0

对不起,第一次没有清楚的问题。我认为你的答案有诀窍可以首先使用任何算法对项目进行排序,然后使用您的算法确定每列中应该包含多少个项目。 再次抱歉不清楚问题。 – 2009-08-07 12:28:34

+0

@布莱恩:没问题。现在更新以回答您更新的问题。 – RichieHindle 2009-08-07 12:33:16

8

这个答案现在已经过时了,因为OP在我回答后决定简单地改变问题。我只是懒得删除它。

function getColumnItemCount(int items, int column) { 
    return (int) (items/3) + (((items % 3) >= (column + 1)) ? 1 : 0); 
} 
+0

一旦我发现“列”预计从0开始计数,与序列列号相反,这很有用。 :D – pchap10k 2010-01-12 10:51:33

+0

当您处理少量内容时,大多数这些答案都不起作用。尝试使用5个值的认可解决方案,最终只有两列!这一个似乎可靠地工作,无论你抛出什么 - 如果你通过它传递'3'作为列计数变量,那么它将是完美的任何用例(: – pospi 2014-03-19 02:19:02

4

只是给你一个提示(这是很容易的,所以找出自己)3

鸿沟ItemCount中,舍去。至少在每一栏中都是这样。

现在你做ItemCount%3(模),它可以是1或2(因为否则它可以被3除,右),你分发它。

1

你只是想要在每列的项目数?如果你有n项,然后 计数将是:

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

其中 “圆” 四舍五入到最接近的整数(例如圆(X)=(INT)(X + 0.5))

如果要真正把项目有,尝试这样的事情Python样式的伪代码:

def columnize(items): 
    i=0 
    answer=[ [], [], [] ] 
    for it in items: 
    answer[i%3] += it 
    i += 1 
    return answer 
+0

你的第一行代码分发10作为(3,3,4)和11(as)(4,4,3)。 – 2009-08-07 12:09:50

+0

你是对的,它的确如此,这些数字总结得当,解决方案符合我阅读的要求:没有列有更多如果你想让这些值反映你从第二个代码块得到的计数,那么我认为你可以使用上面的RichieHindle的代码。 – redtuna 2009-08-07 12:31:52

+0

公平的 - 从那以后规范已经改变了。 – 2009-08-07 13:59:34

2

这是很简单的

如果你有N元素从索引到N-10索引到2立柱,i个元素会在列i mod 3(其中mod是求余运算,%在C,C++和其他一些语言)

+0

在阅读你的回复之后,我想,“这很容易,为什么我没有想到这个”,然后我意识到这个问题还有更多的问题,请参阅编辑 – 2009-08-07 12:15:24

0

下面是一个PHP的版本我砍死在一起,所有的PHP黑客有像我(烨,株连关联!)

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

你可以这样调用...

$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); 

信用这个应该去@Bombe谁在Java中(?)只要它上面。

注意:此函数期望您传递序号列号,即第一个col = 1,第二个col = 2等...

3

我需要所以这里一个C#版本就是我想出了(该算法是从里奇的回答):

// Start with 11 values 
var data = "ABCDEFGHIJK"; 

// Split in 3 columns 
var columnCount = 3; 

// Find out how many values to display in each column 
var columnCounts = new int[columnCount]; 
for (int i = 0; i < columnCount; i++) 
    columnCounts[i] = (data.Count() + columnCount - (i + 1))/columnCount; 

// Allocate each value to the appropriate column 
int iData = 0; 
for (int i = 0; i < columnCount; i++) 
for (int j = 0; j < columnCounts[i]; j++) 
    Console.WriteLine("{0} -> Column {1}", data[iData++], i + 1); 

// PRINTS: 
// A -> Column 1 
// B -> Column 1 
// C -> Column 1 
// D -> Column 1 
// E -> Column 2 
// F -> Column 2 
// G -> Column 2 
// H -> Column 2 
// I -> Column 3 
// J -> Column 3 
// K -> Column 3 
5

这个问题是最接近我自己,我发现,所以我会后我提出的解决方案。在JavaScript中:

var items = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K'] 
var columns = [[], [], []] 
for (var i=0; i<items.length; i++) { 
    columns[Math.floor(i * columns.length/items.length)].push(items[i]) 
} 
console.log(columns)