Ich brauche combinatorials (nCr) in Python zu berechnen , aber die Funktion nicht finden können , das zu tun in math
, numpy
oder stat
Bibliotheken. So etwas wie eine Funktion des Typs:
comb = calculate_combinations(n, r)
Ich brauche die Anzahl der möglichen Kombinationen, nicht die tatsächlichen Kombinationen, also itertools.combinations
interessiert mich das nicht.
Schließlich möchte ich die Verwendung von Fakultäten vermeiden, da die Zahlen, für die ich die Kombinationen berechnen werde, zu groß werden können und die Fakultäten monströs sein werden.
Dies scheint eine WIRKLICH einfach zu beantwortende Frage zu sein, aber ich bin in Fragen über das Generieren aller tatsächlichen Kombinationen ertrunken, was ich nicht will.
quelle
scipy.misc.comb
ist zugunstenscipy.special.comb
seit Version veraltet0.10.0
.Warum schreibst du es nicht selbst? Es ist ein Einzeiler oder so:
Test - Drucken des Pascalschen Dreiecks:
PS. bearbeitet, um
int(round(reduce(mul, (float(n-i)/(i+1) for i in range(k)), 1)))
durch zu ersetzen,int(reduce(mul, (Fraction(n-i, i+1) for i in range(k)), 1))
damit es nicht für große N / K irrtquelle
from functools import reduce
.Eine schnelle Suche nach Google-Code ergibt (es wird eine Formel aus der Antwort von @Mark Byers verwendet ):
choose()
ist 10 mal schneller (getestet an allen 0 <= (n, k) <1e3 Paaren) alsscipy.misc.comb()
wenn Sie eine genaue Antwort benötigen.quelle
choose
Funktion sollte viel mehr Up-Votes haben! Python 3.8 hat math.comb, aber ich musste Python 3.6 für eine Herausforderung verwenden, und keine Implementierung lieferte genaue Ergebnisse für sehr große Ganzzahlen. Dieser macht und macht es schnell!Wenn Sie genaue Ergebnisse und Geschwindigkeit wünschen , versuchen Sie es mit gmpy -
gmpy.comb
sollte genau das tun, wonach Sie fragen, und es ist ziemlich schnell (natürlichgmpy
bin ich als Originalautor voreingenommen ;-).quelle
gmpy2.comb()
ist 10-mal schneller alschoose()
aus meiner Antwort für den Code:for k, n in itertools.combinations(range(1000), 2): f(n,k)
Wof()
ist entwedergmpy2.comb()
oderchoose()
auf Python 3.Wenn Sie ein genaues Ergebnis wünschen, verwenden Sie
sympy.binomial
. Es scheint zweifellos die schnellste Methode zu sein.quelle
Eine wörtliche Übersetzung der mathematischen Definition ist in vielen Fällen völlig ausreichend (wobei zu beachten ist, dass Python automatisch eine Arithmetik mit großen Zahlen verwendet):
Bei einigen von mir getesteten Eingaben (z. B. n = 1000 r = 500) war dies mehr als zehnmal schneller als der eine Liner
reduce
, der in einer anderen (derzeit am höchsten bewerteten) Antwort vorgeschlagen wurde. Auf der anderen Seite wird es von dem von @JF Sebastian bereitgestellten Snippit übertroffen.quelle
Ab
Python 3.8
sofort enthält die Standardbibliothek jetzt diemath.comb
Funktion zur Berechnung des Binomialkoeffizienten:Dies ist die Anzahl der Möglichkeiten, k Elemente aus n Elementen ohne Wiederholung auszuwählen
n! / (k! (n - k)!)
:quelle
Hier ist eine andere Alternative. Dieser wurde ursprünglich in C ++ geschrieben, sodass er für eine Ganzzahl mit endlicher Genauigkeit (z. B. __int64) nach C ++ zurückportiert werden kann. Der Vorteil besteht darin, dass (1) nur ganzzahlige Operationen erforderlich sind und (2) das Aufblähen des ganzzahligen Werts durch aufeinanderfolgende Multiplikations- und Divisionspaare vermieden wird. Ich habe das Ergebnis mit Nas Banovs Pascal-Dreieck getestet, es erhält die richtige Antwort:
Begründung: Um die Anzahl der Multiplikationen und Divisionen zu minimieren, schreiben wir den Ausdruck wie folgt um
Um einen Multiplikationsüberlauf so weit wie möglich zu vermeiden, werden wir in der folgenden STRICT-Reihenfolge von links nach rechts auswerten:
Wir können zeigen, dass die in dieser Reihenfolge betriebene Ganzzahlarithmetik genau ist (dh kein Rundungsfehler).
quelle
Bei dynamischer Programmierung beträgt die zeitliche Komplexität Θ (n * m) und die räumliche Komplexität Θ (m):
quelle
Wenn Ihr Programm eine Obergrenze für
n
(sagen wirn <= N
) hat und nCr wiederholt berechnen muss (vorzugsweise für >>N
Zeiten), kann die Verwendung von lru_cache zu einer enormen Leistungssteigerung führen:Das Erstellen des Caches (was implizit erfolgt) nimmt
O(N^2)
Zeit in Anspruch. Alle nachfolgenden Anrufe annCr
werden zurückgegebenO(1)
.quelle
Sie können 2 einfache Funktionen schreiben, die sich tatsächlich als 5-8-mal schneller herausstellen als mit scipy.special.comb . Tatsächlich müssen Sie keine zusätzlichen Pakete importieren, und die Funktion ist recht gut lesbar. Der Trick besteht darin, die zuvor berechneten Werte mithilfe der Memoisierung zu speichern und die Definition von nCr zu verwenden
Wenn wir mal vergleichen
quelle
Mit Sympy ist das ziemlich einfach.
quelle
Verwenden Sie nur die mit Python vertriebene Standardbibliothek :
quelle
Die direkte Formel erzeugt große ganze Zahlen, wenn n größer als 20 ist.
Also noch eine Antwort:
kurz, genau und effizient, da dies große Python-Ganzzahlen vermeidet, indem es bei Longs bleibt.
Es ist genauer und schneller im Vergleich zu scipy.special.comb:
quelle
range(n-r+1, n+1)
statt seinrange(n-r,n+1)
.Dies ist der @ KillerT2333-Code, der den integrierten Memoization Decorator verwendet.
quelle
Hier ist ein effizienter Algorithmus für Sie
Zum Beispiel nCr (30,7) = Fakt (30) / (Fakt (7) * Fakt (23)) = (30 * 29 * 28 * 27 * 26 * 25 * 24) / (1 * 2 * 3 * 4 * 5 * 6 * 7)
Führen Sie also einfach die Schleife von 1 nach r aus, um das Ergebnis zu erhalten.
quelle
Das ist wahrscheinlich so schnell, wie Sie es in reinem Python für relativ große Eingaben tun können:
quelle
Diese Funktion ist sehr optimiert.
quelle