Zunächst einige Definitionen:
- Gegeben
n
undk
betrachten Sie die sortierte Liste der Multisets , wobei wir für jedes Multisetk
Zahlen{0, 1, ..., n-1}
mit Wiederholungen auswählen .
Zum Beispiel für n=5
und k=3
haben wir:
[(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 1), ( 0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 3), (0, 3, 4), (0, 4, 4), (1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4) , (2, 2, 2), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), ( 3, 3, 3), (3, 3, 4), (3, 4, 4), (4, 4, 4)]
- Ein Teil ist eine Liste von Multisets mit der Eigenschaft, dass die Größe des Schnittpunkts aller Multisets im Teil mindestens beträgt
k-1
. Das heißt, wir nehmen alle Multisets und schneiden sie (unter Verwendung der Multiset-Schnittmenge) auf einmal. Als Beispiel[(1, 2, 2), (1, 2, 3), (1, 2, 4)]
ist ein Teil, da sein Schnittpunkt die Größe 2 hat, aber[(1, 1, 3),(1, 2, 3),(1, 2, 4)]
nicht, weil sein Schnittpunkt die Größe 1 hat.
Aufgabe
Ihr Code sollte zwei Argumente n
und k
. Es sollte dann diese Multisets gierig in sortierter Reihenfolge durchgehen und die Teile der Liste ausgeben. Für den Fall n=5, k=3
lautet die richtige Partitionierung:
(0, 0, 0), (0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4)
(0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4)
(0, 2, 2), (0, 2, 3), (0, 2, 4)
(0, 3, 3), (0, 3, 4)
(0, 4, 4)
(1, 1, 1), (1, 1, 2), (1, 1, 3), (1, 1, 4)
(1, 2, 2), (1, 2, 3), (1, 2, 4)
(1, 3, 3), (1, 3, 4)
(1, 4, 4)
(2, 2, 2), (2, 2, 3), (2, 2, 4)
(2, 3, 3), (2, 3, 4)
(2, 4, 4)
(3, 3, 3), (3, 3, 4)
(3, 4, 4), (4, 4, 4)
Hier ist ein weiteres Beispiel für n = 4, k = 4
.
(0, 0, 0, 0), (0, 0, 0, 1), (0, 0, 0, 2), (0, 0, 0, 3)
(0, 0, 1, 1), (0, 0, 1, 2), (0, 0, 1, 3)
(0, 0, 2, 2), (0, 0, 2, 3)
(0, 0, 3, 3)
(0, 1, 1, 1), (0, 1, 1, 2), (0, 1, 1, 3)
(0, 1, 2, 2), (0, 1, 2, 3)
(0, 1, 3, 3)
(0, 2, 2, 2), (0, 2, 2, 3)
(0, 2, 3, 3), (0, 3, 3, 3)
(1, 1, 1, 1), (1, 1, 1, 2), (1, 1, 1, 3)
(1, 1, 2, 2), (1, 1, 2, 3)
(1, 1, 3, 3)
(1, 2, 2, 2), (1, 2, 2, 3)
(1, 2, 3, 3), (1, 3, 3, 3)
(2, 2, 2, 2), (2, 2, 2, 3)
(2, 2, 3, 3), (2, 3, 3, 3)
(3, 3, 3, 3)
Klarstellung, was gierig bedeutet: Für jedes Multiset prüfen wir wiederum, ob es dem vorhandenen Teil hinzugefügt werden kann. Wenn es geht, fügen wir es hinzu. Wenn es nicht geht, beginnen wir ein neues Teil. Wir betrachten die Multisets in sortierter Reihenfolge wie im obigen Beispiel.
Ausgabe
Sie können die Partitionierung in einem beliebigen Format ausgeben. Multisets sollten jedoch horizontal in eine Zeile geschrieben werden. Das heißt, ein einzelnes Multiset sollte nicht vertikal geschrieben oder über mehrere Zeilen verteilt werden. Sie können auswählen, wie Sie die Darstellung von Teilen in der Ausgabe trennen möchten.
Annahmen
Das können wir annehmen n >= k > 0
.
quelle
(0, 4, 4)
? Angesichts Ihrer Beschreibung würde ich denken, dass sein "Teil" wäre(0, 4, 4), (1, 4, 4), (2, 4, 4), (3, 4, 4), (4, 4, 4)
. Ähnliches gilt für(0, 0, 3, 3)
den zweiten Testfall.Antworten:
Gelee ,
2625 BytesVollständiges Programm, das eine Darstellung einer Liste von Listen druckt, wobei jede Liste ein Teil ist, z. B. für n = 5, k = 3:
Hinweis: Die verwendete Darstellung entfernt die redundanten
[
und]
um Listen der Länge 1.Probieren Sie es online aus! oder sehen Sie eine hübsche Druckversion (kostet 3 Bytes)
Wie?
quelle
MATLAB, 272 Bytes
Ausgabe:
Zwei leere Zeilen zwischen verschiedenen Teilen.
Ungolfed:
Erläuterung:
Zuerst finden wir alle Multisets mit roher Gewalt:
repmat(0:n-1, 1, k)
wiederholt den Vektor der Werte von0
bis zun-1
k
Zeiten.nchoosek(x, k)
gibt eine Matrix zurück, die alle k-Kombinationen des wiederholten Vektors enthält.sort(x, 2)
sortiert alle k-Kombinationen undunique(x, 'rows')
entfernt dann alle Duplikate.p=zeros(0,k);
Erstellt eine leere Matrix mitk
Spalten. Wir werden es als Stapel verwenden. Bei jeder Iteration der äußerstenfor
Schleife fügen wir zuerst das aktuelle Multiset zu diesem Stapel hinzu :p=[p;l(i,:)];
.Dann prüfen wir
k-1
mit dem folgenden Code , ob der Schnittpunkt aller Multisets im Stapel mindestens lang ist (wir können denintersect
Befehl MATLAB nicht verwenden , um nach den Schnittpunkten zu suchen, da er eine Menge zurückgibt, aber wir benötigen einen Multiset):Nun, wenn die Kreuzung
a == 0
sonst lang genug ista == 1
.Wenn die Kreuzung nicht lang genug ist, drucken wir eine neue Zeile und leeren den Stapel:
Dann drucken wir einfach das aktuelle Multiset:
quelle
MATL , 34 Bytes
Teile werden durch eine Zeile mit Leerzeichen getrennt.
Probieren Sie es online aus!
Erläuterung
Haftungsausschluss: Diese Methode scheint zu funktionieren (und in den Testfällen auch), aber ich habe keinen Beweis dafür, dass dies immer der Fall ist
Multisets werden sowohl intern (dh jedes Multiset hat nicht abnehmende Einträge) als auch extern (dh Multiset M steht vor Multiset N, wenn M lexikographisch vor N steht ) sortiert .
Um den Multiset-Schnittpunkt zu berechnen, werden die sortierten Multisets als Zeilen einer Matrix angeordnet und aufeinanderfolgende Differenzen werden entlang jeder Spalte berechnet. Wenn alle Spalten außer höchstens einer alle Differenzen gleich Null haben, gehören die Multisets zum selben Teil.
Dieser Test würde ein falsches negatives Ergebnis für Multimengen geben , wie
(1,2,3)
und(2,3,4)
: selbst wenn2
,3
sind gemeinsame Einträge, würden sie nicht als solche erkannt werden , weil sie in nicht passenden Spalten sind.Dies scheint jedoch zumindest in den Testfällen kein Problem zu sein. Es scheint, dass ein Test zwischen Multisets wie
1,2,3
und2,3,4
nie wirklich durchgeführt werden muss, da einige Zwischen-Multisets ein negatives Ergebnis lieferten und sich daher bereits in verschiedenen Teilen befinden. Wenn dies tatsächlich zutrifft, hat der Grund zweifellos damit zu tun, dass die Multisets sortiert sind.Ich habe jedoch keinen Beweis dafür. Es scheint einfach zu funktionieren.
quelle
n=k=4
Fall , in dem wir einen neuen Teil beginnen(0, 0, 3, 3)
, der vektorisierte aufeinanderfolgende Unterschied zwischen diesem und dem vorherigen Mehrfachsatz(0, 0, 2, 3)
nur einen Unterschied hat. Wie macht der " bisherige Teil" diese Arbeit? (oder gleichwertig, was war das vorherige Schritt Ergebnis, das anstelle von verwendet wurde(0, 0, 2, 3)
?)PHP, 245 Bytes
Probieren Sie es online aus!
Erweitert
Ausgabe als String
n> 15 für mehr Präzision
quelle
0
für(16**16-1)%16
und die lange Version arbeitet nur mit der Präzision, die für benötigt wird,n>15
bcmod(bcsub(bcpow(16,16),1),16)
ist15
php.net/manual/en/ref.bc.php