2009-08-07 11 views
4

Ich bin auf der Suche nach einem Algorithmus, der 1 bis viele Elemente gleichmäßig in drei Spalten verteilt. Keine Spalte kann mehr als einen weiteren Eintrag als jede andere Spalte enthalten. Ich tippte unten ein Beispiel von dem, wonach ich suche. Das Addieren von Col1, Col2 und Col3 sollte ItemCount entsprechen.Algorithmus zum gleichmäßigen Verteilen von Objekten in 3 Spalten

Bearbeiten: Auch die Elemente sind alphanumerisch und müssen innerhalb der Spalte angeordnet werden. Das letzte Element in der Spalte muss kleiner als das erste Element in der nächsten Spalte sein.

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: Bitte nehmen Sie sich etwas Zeit, um die richtige Frage zum ersten Mal zu stellen. Sieben Leute haben sich sehr viel Mühe gegeben, die erste Version Ihrer Frage zu beantworten, und jetzt ist sie so verändert, dass der größte Teil dieser Arbeit verschwendet wurde. – RichieHindle

+0

Könnte die Verteilung für ABCD A | BC | D oder A | B | CD sein? – christopheml

Antwort

11

Hier, in Python (wo mod der Modulo-Operator, % in C, C++ und einige anderen Sprachen sind):

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

Sorry, dass die Frage beim ersten Mal nicht klar wurde. Ich denke, deine Antwort macht den Trick Sie können die Artikel zuerst mit einem beliebigen Algorithmus sortieren und dann Ihren verwenden, um herauszufinden, wie viele Artikel in jeder Spalte enthalten sein sollten. Nochmals Entschuldigung dafür, dass ich in der Frage nicht klar bin. –

+0

@ Brian: Kein Problem. Jetzt aktualisiert, um Ihre aktualisierte Frage zu beantworten. – RichieHindle

8

Diese Antwort ist jetzt veraltet, weil das OP entschied, die Frage einfach zu ändern, nachdem ich es geantwortet habe. Ich bin einfach zu faul, um es zu löschen.

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

Dies war nützlich, sobald ich herausgefunden habe, dass "Spalte" von 0 erwartet wird, im Gegensatz zu der Ordnungsspaltennummer. : D – pchap10k

+0

Die meisten dieser Antworten funktionieren nicht, wenn Sie mit einer kleinen Menge von Inhalten zu tun haben. Versuchen Sie die genehmigte Lösung mit 5 Werten und Sie werden nur zwei Spalten haben! Dieser scheint zuverlässig zu arbeiten, egal, was Sie darauf werfen - wenn Sie ihn generierten, um die "3" als Spaltenzahlvariable weiterzugeben, dann wäre er perfekt für jeden Anwendungsfall (: – pospi

4

nur Ihnen einen Hinweis geben (es ziemlich einfach ist, so herauszufinden, selbst)

divide ItemCount von 3 Abrunden. Das ist zumindest in jeder Spalte.

Jetzt machen Sie ItemCount% 3 (modulo), das ist entweder 1 oder 2 (weil sonst wäre es durch 3 teilbar, rechts) und Sie verteilen das.

1

Möchten Sie nur die Anzahl der Elemente in jeder Spalte? Wenn Sie n Einzelteile haben, dann die Zählungen werden:

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

wo "rund" Runde auf die nächste ganze Zahl (zB Runde (x) = (int) (x + 0,5))

Wenn Sie möchten die Elemente es tatsächlich setzen, versuchen Sie so etwas wie dieses Python-Stil Pseudo-Code:

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

). Ihre erste Codezeile verteilt 10 als (3,3,4), und 11 als (4,4,3). –

+0

Sie haben recht, es tut. Diese Zahlen summieren sich aber richtig.Die Lösung entspricht den Anforderungen, wie ich sie gelesen habe: keine Spalte hat mehr Wenn Sie möchten, dass die Werte die Zählungen widerspiegeln, die Sie vom zweiten Codeblock erhalten, dann können Sie den Code von RichieHindle oben verwenden. – redtuna

+0

Gut genug - die Spezifikationen haben sich seitdem geändert. –

2

Es ist ganz einfach

Wenn Sie N Elemente indiziert aushabenzu N-1 und Spalte 0-2 indiziert, das i -te Element wird in der Spalte geht i mod 3

+0

Nachdem ich Ihre Antwort gelesen hatte, dachte ich: "Hm, das war einfach, warum habe ich nicht daran gedacht." Und dann wurde mir klar, dass es mehr zu der Frage gab. Siehe die Bearbeitung. –

0

Hier ist eine PHP-Version, die ich zusammen für alle wie mich die PHP Hacks gibt gehackt (yup, Schuld durch Assoziation!)

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

Und Sie können es so nennen ...

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

Kredit für das sollte gehen @Bombe, die es in Java zur Verfügung gestellt (?) Oben.

Hinweis: Diese Funktion erwartet, dass Sie eine Ordinalspaltennummer übergeben, d. H. Erste Spalte = 1, zweite Spalte = 2 usw.

3

brauchte ich eine C# Version also hier ist, was ich mit aufkommen (der Algorithmus von Richies Antwort):

// 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

Diese Frage wurde die nächste Sache, meinen eigenen, dass ich gefunden, ich werde so schreiben Die Lösung, die ich mir ausgedacht habe. In 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) 
Verwandte Themen