counting combinations and permutations efficiently

后端 未结 13 1981
佛祖请我去吃肉
佛祖请我去吃肉 2020-12-02 12:38

I have some code to count permutations and combinations, and I\'m trying to make it work better for large numbers.

I\'ve found a better algorithm for permutations th

相关标签:
13条回答
  • 2020-12-02 13:14
    from scipy import misc
    misc.comb(n, k)
    

    should allow you to count combinations

    0 讨论(0)
  • 2020-12-02 13:14
    from numpy import prod
    
    def nCr(n,r):
        numerator = range(n, max(n-r,r),-1)
        denominator = range(1, min(n-r,r) +1,1)
        return int(prod(numerator)/prod(denominator))
    
    0 讨论(0)
  • 2020-12-02 13:14

    Using xrange() instead of range() will speed things up slightly due to the fact that no intermediate list is created, populated, iterated through, and then destroyed. Also, reduce() with operator.mul.

    0 讨论(0)
  • 2020-12-02 13:16

    If your problem does not require knowing the exact number of permutations or combinations, then you could use Stirling's approximation for the factorial.

    That would lead to code like this:

    import math
    
    def stirling(n):
        # http://en.wikipedia.org/wiki/Stirling%27s_approximation
        return math.sqrt(2*math.pi*n)*(n/math.e)**n
    
    def npr(n,r):
        return (stirling(n)/stirling(n-r) if n>20 else
                math.factorial(n)/math.factorial(n-r))
    
    def ncr(n,r):    
        return (stirling(n)/stirling(r)/stirling(n-r) if n>20 else
                math.factorial(n)/math.factorial(r)/math.factorial(n-r))
    
    print(npr(3,2))
    # 6
    print(npr(100,20))
    # 1.30426670868e+39
    print(ncr(3,2))
    # 3
    print(ncr(100,20))
    # 5.38333246453e+20
    
    0 讨论(0)
  • 2020-12-02 13:17

    There's a function for this in scipy which hasn't been mentioned yet: scipy.special.comb. It seems efficient based on some quick timing results for your doctest (~0.004 seconds for comb(100000, 1000, 1) == comb(100000, 99000, 1)).

    [While this specific question seems to be about algorithms the question is there a math ncr function in python is marked as a duplicate of this...]

    0 讨论(0)
  • 2020-12-02 13:18

    If you are computing N choose K (which is what I think you're doing with ncr), there is a dynamic programming solution that may be a lot faster. This will avoid factorial, plus you can keep the table if you want for later use.

    Here is a teaching link for it:

    http://www.csc.liv.ac.uk/~ped/teachadmin/algor/dyprog.html

    I am unsure of how to better solve your first problem, though, sorry.

    Edit: Here is the mock-up. There are some pretty hilarious off-by-one errors, so it can certainly stand some more clean up.

    import sys
    n = int(sys.argv[1])+2#100
    k = int(sys.argv[2])+1#20
    table = [[0]*(n+2)]*(n+2)
    
    for i in range(1,n):
        table[i][i] = 1
    for i in range(1,n):
        for j in range(1,n-i):
            x = i+j
            if j == 1: table[x][j] = 1
            else: table[x][j] = table[x-1][j-1] + table[x-1][j]
    
    print table[n][k]
    
    0 讨论(0)
提交回复
热议问题