Я ищу алгоритм, который равномерно распределяет от 1 до многих элементов по трем столбцам. Ни в одном столбце не может быть более одного элемента, чем в любом другом столбце. Я набрал пример того, что ищу ниже. Сумма Col1, Col2 и Col3 должна равняться ItemCount.

Изменить: Кроме того, элементы являются буквенно-цифровыми и должны быть упорядочены в столбце. Последний элемент в столбце должен быть меньше первого элемента в следующем столбце.

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
4
Brian Bolton 7 Авг 2009 в 15:53

8 ответов

Лучший ответ

Вот и все, в 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
11
RichieHindle 7 Авг 2009 в 12:32

Этот ответ теперь устарел, потому что OP решил просто изменить вопрос после того, как я ответил на него. Мне просто лень его удалять.

function getColumnItemCount(int items, int column) {
    return (int) (items / 3) + (((items % 3) >= (column + 1)) ? 1 : 0);
}
8
Bombe 7 Авг 2009 в 12:51

Этот вопрос был самым близким к моему собственному, поэтому я опубликую решение, которое придумал. В 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)
6
gsf 10 Июл 2012 в 23:22

Просто чтобы дать вам подсказку (это довольно просто, так что разберитесь сами)

Разделите ItemCount на 3, округлив в меньшую сторону. Это то, что есть по крайней мере в каждом столбце.

Теперь вы делаете ItemCount% 3 (по модулю), который равен 1 или 2 (иначе он мог бы делиться на 3, верно), и распределяете его.

5
Johannes Rudolph 7 Авг 2009 в 12:07

Это довольно просто

Если у вас есть элементы N, проиндексированные от 0 до N-1, а столбец проиндексирован от 0 до 2, i -й элемент войдет в столбец i mod 3 (где mod - оператор по модулю, % в C, C ++ и некоторых других языках)

2
ThibThib 7 Авг 2009 в 12:03

Вам просто нужно количество элементов в каждом столбце? Если у вас есть n предметов, то подсчет будет следующим:

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

Где "round" округляется до ближайшего целого числа (например, round (x) = (int) (x + 0.5))

Если вы действительно хотите поместить туда элементы, попробуйте что-то вроде этого псевдокода в стиле Python:

def columnize(items):
  i=0
  answer=[ [], [], [] ]
  for it in items:
    answer[i%3] += it
    i += 1
  return answer
1
redtuna 7 Авг 2009 в 12:02

Вот версия 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 (?) Выше.

NB: эта функция ожидает, что вы передадите порядковый номер столбца, то есть первый столбец = 1, второй столбец = 2 и т. д.

0
pchap10k 12 Янв 2010 в 10:57

Мне нужна была версия 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
3
Xavier Poinas 10 Окт 2011 в 01:06