Saya perlu menghitung kombinatorial (nCr) dengan Python tetapi tidak dapat menemukan fungsi untuk melakukannya di math
, numpy
atau stat
perpustakaan. Sesuatu seperti fungsi dari tipe:
comb = calculate_combinations(n, r)
Saya membutuhkan jumlah kombinasi yang mungkin, bukan kombinasi yang sebenarnya, jadi itertools.combinations
saya tidak tertarik.
Terakhir, saya ingin menghindari penggunaan faktorial, karena angka yang akan saya hitung kombinasinya bisa menjadi terlalu besar dan faktorialnya akan menjadi sangat besar.
Ini sepertinya pertanyaan yang BENAR-BENAR mudah dijawab, namun saya tenggelam dalam pertanyaan tentang menghasilkan semua kombinasi yang sebenarnya, yang bukan itu yang saya inginkan.
sumber
scipy.misc.comb
tidak digunakan lagiscipy.special.comb
karena versi0.10.0
.Mengapa tidak menulisnya sendiri? Ini satu baris atau semacamnya:
Tes - mencetak segitiga Pascal:
PS. diedit untuk diganti
int(round(reduce(mul, (float(n-i)/(i+1) for i in range(k)), 1)))
denganint(reduce(mul, (Fraction(n-i, i+1) for i in range(k)), 1))
sehingga tidak akan salah untuk N / K besarsumber
from functools import reduce
.Pencarian cepat di kode google memberikan (menggunakan rumus dari jawaban @Mark Byers ):
choose()
adalah 10 kali lebih cepat (diuji pada semua 0 <= (n, k) <1e3 pasangan) dibandingkanscipy.misc.comb()
jika Anda membutuhkan jawaban yang tepat.sumber
choose
Fungsi ini seharusnya mendapatkan lebih banyak suara! Python 3.8 memiliki math.comb, tetapi saya harus menggunakan Python 3.6 untuk tantangan dan tidak ada implementasi yang memberikan hasil yang tepat untuk integer yang sangat besar. Yang ini melakukannya dan melakukannya dengan cepat!Jika Anda ingin hasil yang tepat dan kecepatan, coba gmpy -
gmpy.comb
harus melakukan apa yang Anda minta, dan itu cukup cepat (tentu saja, sebagaigmpy
's penulis asli, saya sedang bias ;-).sumber
gmpy2.comb()
10 kali lebih cepat daripadachoose()
dari jawaban saya untuk kode: difor k, n in itertools.combinations(range(1000), 2): f(n,k)
manaf()
adagmpy2.comb()
atauchoose()
di Python 3.Jika Anda menginginkan hasil yang tepat, gunakan
sympy.binomial
. Tampaknya ini metode tercepat, tangan ke bawah.sumber
Terjemahan literal dari definisi matematika cukup memadai dalam banyak kasus (mengingat bahwa Python akan secara otomatis menggunakan aritmatika angka besar):
Untuk beberapa masukan yang saya uji (misalnya n = 1000 r = 500) ini lebih dari 10 kali lebih cepat daripada satu baris yang
reduce
disarankan dalam jawaban lain (saat ini dengan suara terbanyak). Di sisi lain, itu dilakukan oleh cuplikan yang disediakan oleh @JF Sebastian.sumber
Memulai
Python 3.8
, pustaka standar sekarang menyertakanmath.comb
fungsi untuk menghitung koefisien binomial:yaitu banyaknya cara untuk memilih k item dari n item tanpa pengulangan
n! / (k! (n - k)!)
:sumber
Berikut alternatif lain. Yang ini aslinya ditulis dalam C ++, sehingga dapat di-backport ke C ++ untuk integer presisi hingga (mis. __Int64). Keuntungannya adalah (1) hanya melibatkan operasi integer, dan (2) menghindari pembengkakan nilai integer dengan melakukan pasangan perkalian dan pembagian yang berurutan. Saya telah menguji hasilnya dengan segitiga Pascal Nas Banov, hasilnya benar:
Rasional: Untuk meminimalkan # perkalian dan pembagian, kami menulis ulang ekspresi sebagai
Untuk menghindari kelimpahan perkalian sebanyak mungkin, kami akan mengevaluasi dalam urutan STRICT berikut, dari kiri ke kanan:
Kita dapat menunjukkan bahwa aritmatika integer yang dioperasikan dalam urutan ini adalah tepat (yaitu tidak ada kesalahan pembulatan).
sumber
Menggunakan pemrograman dinamis, kompleksitas waktu adalah Θ (n * m) dan kompleksitas ruang Θ (m):
sumber
Jika program Anda memiliki batas atas
n
(katakanlahn <= N
) dan perlu menghitung nCr berulang kali (sebaiknya untuk >>N
kali), menggunakan lru_cache dapat memberi Anda peningkatan kinerja yang besar:Membangun cache (yang dilakukan secara implisit) membutuhkan
O(N^2)
waktu. Setiap panggilan berikutnya kenCr
akan kembali masukO(1)
.sumber
Anda dapat menulis 2 fungsi sederhana yang ternyata sekitar 5-8 kali lebih cepat daripada menggunakan scipy.special.comb . Faktanya, Anda tidak perlu mengimpor paket tambahan apa pun, dan fungsinya cukup mudah dibaca. Triknya adalah dengan menggunakan memoization untuk menyimpan nilai yang dihitung sebelumnya, dan menggunakan definisi nCr
Jika kita membandingkan waktu
sumber
Sangat mudah dengan sympy.
sumber
Hanya menggunakan pustaka standar yang didistribusikan dengan Python :
sumber
Rumus langsung menghasilkan bilangan bulat besar jika n lebih besar dari 20.
Jadi, tanggapan lain:
pendek, akurat dan efisien karena ini menghindari bilangan bulat besar python dengan bertahan dengan rindu.
Ini lebih akurat dan lebih cepat jika dibandingkan dengan scipy.special.comb:
sumber
range(n-r+1, n+1)
bukanrange(n-r,n+1)
.Ini adalah kode @ killerT2333 menggunakan dekorator memoisasi bawaan.
sumber
Berikut adalah algoritma yang efisien untuk Anda
Misalnya nCr (30,7) = fakta (30) / (fakta (7) * fakta (23)) = (30 * 29 * 28 * 27 * 26 * 25 * 24) / (1 * 2 * 3 * 4 * 5 * 6 * 7)
Jadi jalankan saja loop dari 1 ke r bisa mendapatkan hasilnya.
sumber
Itu mungkin secepat Anda bisa melakukannya dengan python murni untuk input yang cukup besar:
sumber
Fungsi ini sangat dioptimalkan.
sumber