Gegeben:
- Eine natürliche Zahl S .
- Eine Liste von N rationalen Gewichten W , die sich zu 1 summieren.
Geben Sie eine Liste L von N nicht negativen ganzen Zahlen zurück, so dass:
(1) sum(L) = S
(2) sum((S⋅W_i - L_i)^2) is minimal
Mit anderen Worten, approximieren Sie S⋅W_i
s mit ganzen Zahlen so genau wie möglich.
Beispiele:
1 [0.4 0.3 0.3] = [1 0 0]
3 [0 1 0] = [0 3 0]
4 [0.3 0.4 0.3] = [1 2 1]
5 [0.3 0.4 0.3] = [2 2 1] or [1 2 2] but not [1 3 1]
21 [0.3 0.2 0.5] = [6 4 11]
5 [0.1 0.2 0.3 0.4] = [1 1 1 2] or [0 1 2 2]
4 [0.11 0.3 0.59] = [1 1 2]
10 [0.47 0.47 0.06] = [5 5 0]
10 [0.43 0.43 0.14] = [4 4 2]
11 [0.43 0.43 0.14] = [5 5 1]
Regeln:
- Sie können ein beliebiges Eingabeformat verwenden oder nur eine Funktion bereitstellen, die die Eingabe als Argumente akzeptiert.
Hintergrund:
Dieses Problem tritt auf, wenn S verschiedener Arten von Gegenständen in verschiedenen Anteilen W i in Bezug auf die Arten angezeigt wird.
Ein weiteres Beispiel für dieses Problem ist die proportionale politische Repräsentation, siehe das Aufteilungsparadoxon . Die letzten beiden Testfälle sind als Alabama-Paradox bekannt.
Als Statistiker erkannte ich dieses Problem als äquivalent zu einem Problem bei der Identifizierung von Stichprobengrößen bei der Durchführung einer geschichteten Stichprobe. In dieser Situation möchten wir den Anteil jeder Schicht in der Stichprobe gleich dem Anteil jeder Schicht in der Bevölkerung machen. - @tomi
quelle
round(A + B) != round(A) + round(B)
eine kurze Lösung einen Einblick in die Vorgänge hier erfordert.L[i] - S*W[i]
quadrierten Abstände anstelle von Regel 2 und Regel 3 zu minimieren . Dies würde sich annähernS*W[i]
.[0 1 2 2]
ist eine andere mögliche Lösung für5 [0.1 0.2 0.3 0.4]
Antworten:
APL, 21
Dies ist eine Übersetzung aus der 37-Byte-CJam-Antwort von aditsu .
Testen Sie es online .
Erläuterung
quelle
Python 2,
9583132125143Mein erster (und zweiter) (und dritter) Algorithmus hatte Probleme. Nach einem (weiteren!) Umschreiben und weiteren Tests ist hier (ich hoffe wirklich) eine korrekte und schnelle Lösung:
Die Quelle vor dem Minifier sieht nun so aus:
Die Tests geben Folgendes zurück:
Dieser Algorithmus ähnelt anderen Antworten hier. Es ist O (1) für num, also hat es die gleiche Laufzeit für ganze Zahlen 10 und 1000000. Es ist theoretisch O (nlogn) für die Anzahl der Gewichte (aufgrund der Sortierung). Wenn dies allen anderen kniffligen Eingabefällen standhält, ersetzt es den folgenden Algorithmus in meiner Programmier-Toolbox.
Bitte verwenden Sie diesen Algorithmus nicht mit etwas, das nicht golfig ist. Ich habe Kompromisse bei der Geschwindigkeit gemacht, um die Quellgröße zu minimieren. Der folgende Code verwendet dieselbe Logik, ist jedoch viel schneller und nützlicher:
Der Wert von num hat keinen wesentlichen Einfluss auf die Geschwindigkeit. Ich habe es mit Werten von 1 bis 10 ^ 19 getestet. Die Ausführungszeit variiert linear mit der Anzahl der Gewichte. Auf meinem Computer dauert es 0,15 Sekunden mit 10 ^ 5 Gewichten und 15 Sekunden mit 10 ^ 7 Gewichten. Beachten Sie, dass die Gewichte nicht auf Brüche beschränkt sind, die sich zu eins summieren. Die hier verwendete Sortiertechnik ist ebenfalls etwa doppelt so schnell wie der traditionelle
sorted((v,i) for i,v in enumerate...)
Stil.Ursprünglicher Algorithmus
Dies war eine Funktion in meiner Toolbox, die ein wenig für Golf modifiziert wurde. Es war ursprünglich aus einer SO-Antwort . Und es ist falsch.
Es gibt eine Annäherung, ist aber nicht immer korrekt, obwohl die Summe (outseq) == num beibehalten wird. Schnell aber nicht zu empfehlen.
Vielen Dank an @alephalpha und @ user23013 für das Erkennen der Fehler.
BEARBEITEN: Setzen Sie totalw (d) auf 1, da OP angibt, dass die Summe der Gewichte immer 1 ist. Jetzt 83 Bytes.
EDIT2: Fehler behoben für [0.4, 0.3, 0.3], 1.
EDIT3: Abgebrochener fehlerhafter Algorithmus. Besser hinzugefügt.
EDIT4: Das wird lächerlich. Ersetzt durch den richtigen (ich hoffe es wirklich) Algorithmus.
EDIT5: Nicht-Golf-Code für andere hinzugefügt, die diesen Algorithmus möglicherweise verwenden möchten.
quelle
a([0.4, 0.3, 0.3], 1)
kehrt zurück[0, 1, 0]
, während die richtige Antwort lautet[1, 0, 0]
.a([0.11,0.3,0.59],4)
zurückgegeben[0, 1, 3]
. Sollte sein[1, 1, 2]
.f([0.47,0.47,0.06],10)
zurückgegeben[5, 4, 1]
. Sollte sein[5, 5, 0]
.Mathematica,
67504645 ZeichenUngolfed:
Beispiel:
quelle
CJam - 37
Probieren Sie es online aus
Erläuterung:
Anmerkungen:
Andere Idee - 46
Probieren Sie es online aus
Dies ist viel einfacher und effizienter, aber leider viel länger. Die Idee hier ist, mit L_i = Etage (S * W_i) zu beginnen, die Differenz (sagen wir D) zwischen S und ihrer Summe zu bestimmen, die D-Indizes mit dem größten Bruchteil von S * W_i zu finden (durch Sortieren und Nehmen von oben D) und inkrementiere L_i für diese Indizes. Komplexität O (N * log (N)).
quelle
:e<
.JavaScript (ES6) 126
130 104 115 156 162 194Nach all den Kommentaren und Testfällen in @ CarpetPythons Antwort zurück zu meinem ersten Algorithmus. Leider funktioniert die intelligente Lösung nicht. Die Implementierung wurde etwas verkürzt, es werden immer noch alle möglichen Lösungen ausprobiert, der quadratische Abstand berechnet und das Minimum eingehalten.
Bearbeiten Für jedes Ausgabeelement mit dem Gewicht w sind 'alle' möglichen Werte nur 2: trunc (w * s) und trunc (w * s) +1, daher gibt es nur (2 ** elemensts) mögliche Lösungen zum Ausprobieren.
Test In Firefox / Firebug - Konsole
Ausgabe
Das ist eine intelligentere Lösung. Single Pass auf Weigth Array.Für jeden Durchgang finde ich den aktuellen Maximalwert in w. Ich ändere diesen Wert an Ort und Stelle mit dem gewichteten ganzzahligen Wert (aufgerundet). Wenn also s == 21 und w = 0,4 sind, erhalten wir 0,5 * 21 -> 10,5 -> 11. Ich speichere diesen Wert negiert, daher kann er nicht in der nächsten Schleife als max gefunden werden. Dann reduziere ich die Gesamtsumme entsprechend (s = s-11) und reduziere auch die Gesamtsumme der Gewichte in der Variablen f.
Die Schleife endet, wenn kein Maximum über 0 gefunden werden kann (alle Werte! = 0 wurden verwaltet).
Zuletzt gebe ich die Werte wieder auf positiv zurück. Warnung Dieser Code ändert das vorhandene Gewichtungsarray, sodass es mit einer Kopie des ursprünglichen Arrays aufgerufen werden muss
Mein erster Versuch
Nicht so eine kluge Lösung. Für jedes mögliche Ergebnis wird der Unterschied ausgewertet und das Minimum beibehalten.
Ungolfed und erklärt
quelle
CJam, 48 Bytes
Eine einfache Lösung für das Problem.
Eingabe geht wie
Erläuterung:
Probieren Sie es hier online aus
quelle
Pyth: 40 Bytes
Dies definiert eine Funktion
g
mit 2 Parametern. Sie können es so nennenMhosm^-*Ghded2C,HNfqsTGmms+*G@Hb}bklHyUHg5 [0.1 0.2 0.3 0.4
.Probieren Sie es online aus: Pyth Compiler / Executor
Erläuterung:
Dies schafft alle möglichen Lösungen
L
, woL[i] = floor(S*W[i])
oderL[i] = floor(S*W[i]+1)
. Zum Beispiel wird die Eingabe4 [0.3 0.4 0.3
erstellt[[1, 1, 1], [2, 1, 1], [1, 2, 1], [1, 1, 2], [2, 2, 1], [2, 1, 2], [1, 2, 2], [2, 2, 2]]
.Nur
[[2, 1, 1], [1, 2, 1], [1, 1, 2]]
bleiben.quelle
Mathematica 108
Erläuterung
Ungolfed
IntegerPartitions[s,{Length@w},0~Range~s]
Gibt alle ganzzahligen Partitionen von zurücks
, wobei Elemente aus der Menge verwendet werden,{0, 1, 2, ...s}
mit der Einschränkung, dass die Ausgabe die gleiche Anzahl von Elementen wie in der Menge der Gewichte enthalten sollw
.Permutations
gibt alle geordneten Anordnungen jeder ganzzahligen Partition an.{Tr[(s *w-#)^2],#}
Gibt{error, permutation}
für jede Permutation eine Liste der geordneten Paare zurück .Sort[...]
sortiert die Liste von{{error1, permutation1},{error2, permutation2}...according to the size of the error.
[[1,2]]]
oderPart[<list>,{1,2}]
gibt das zweite Element des ersten Elements in der sortierten Liste von zurück{{error, permutation}...}
. Mit anderen Worten, es wird die Permutation mit dem kleinsten Fehler zurückgegeben.quelle
R,
858076Verwendet die Hare Quota-Methode.
Ein Paar wurde entfernt, nachdem die Spezifikation angezeigt wurde, dass W 1 ergibt
Testlauf
quelle
Python,
139128117 BytesVorherige itertools-Lösung, 139 Bytes
quelle
O(S^len(W))
eigentlich: P. Neue Lösung ist viel schneller, aber immer noch langsamOctave,
8776Golf:
Ungolfed:
("Endfor" und "Endfunction"! Ich werde nie gewinnen, aber ich spiele gerne Golf mit einer "echten" Sprache.)
quelle
zeros(size(w))
mit0*w
.T-SQL,
167265Weil ich diese Herausforderungen auch gerne in einer Abfrage versuche.
Verwandelte es in eine Inline-Funktion, um die Spezifikation besser anzupassen, und erstellte einen Typ für die Tabellendaten. Es kostete ein bisschen, aber das würde niemals ein Anwärter sein. Jede Anweisung muss separat ausgeführt werden.
In Benutzung
quelle