Python Integer Partitioning with given k partitions

前端 未结 3 1910
灰色年华
灰色年华 2020-11-30 01:45

I\'m trying to find or develop Integer Partitioning code for Python.

FYI, Integer Partitioning is representing a given integer n as a sum of integers smaller than n.

相关标签:
3条回答
  • 2020-11-30 01:57
    def part(n, k):
        def _part(n, k, pre):
            if n <= 0:
                return []
            if k == 1:
                if n <= pre:
                    return [[n]]
                return []
            ret = []
            for i in range(min(pre, n), 0, -1):
                ret += [[i] + sub for sub in _part(n-i, k-1, i)]
            return ret
        return _part(n, k, n)
    

    Example:

    >>> part(5, 1)
    [[5]]
    >>> part(5, 2)
    [[4, 1], [3, 2]]
    >>> part(5, 3)
    [[3, 1, 1], [2, 2, 1]]
    >>> part(5, 4)
    [[2, 1, 1, 1]]
    >>> part(5, 5)
    [[1, 1, 1, 1, 1]]
    >>> part(6, 3)
    [[4, 1, 1], [3, 2, 1], [2, 2, 2]]
    

    UPDATE

    Using memoization:

    def part(n, k):
        def memoize(f):
            cache = [[[None] * n for j in xrange(k)] for i in xrange(n)]
            def wrapper(n, k, pre):
                if cache[n-1][k-1][pre-1] is None:
                    cache[n-1][k-1][pre-1] = f(n, k, pre)
                return cache[n-1][k-1][pre-1]
            return wrapper
    
        @memoize
        def _part(n, k, pre):
            if n <= 0:
                return []
            if k == 1:
                if n <= pre:
                    return [(n,)]
                return []
            ret = []
            for i in xrange(min(pre, n), 0, -1):
                ret += [(i,) + sub for sub in _part(n-i, k-1, i)]
            return ret
        return _part(n, k, n)
    
    0 讨论(0)
  • 2020-11-30 02:08

    First I want to thanks everyone for their contribution. I arrived here needing an algorithm for generating integer partitions with the following details :

    Generate partitions of a number into EXACTLY k parts but also having MINIMUM and MAXIMUM constraints.

    Therefore, I modified the code of "Snakes and Coffee" to accommodate these new requirements:

    def partition_min_max(n,k,l, m):
    '''n is the integer to partition, k is the length of partitions, 
    l is the min partition element size, m is the max partition element size '''
    if k < 1:
        raise StopIteration
    if k == 1:
        if n <= m and n>=l :
            yield (n,)
        raise StopIteration
    for i in range(l,m+1):
        for result in partition_min_max(n-i,k-1,i,m):                
            yield result+(i,)
    
    
    >>> x = list(partition_min_max(20 ,3, 3, 10 ))
    >>> print(x)
    >>> [(10, 7, 3), (9, 8, 3), (10, 6, 4), (9, 7, 4), (8, 8, 4), (10, 5, 5), (9, 6, 5), (8, 7, 5), (8, 6, 6), (7, 7, 6)]
    
    0 讨论(0)
  • 2020-11-30 02:11

    I've written a generator solution

    def partitionfunc(n,k,l=1):
        '''n is the integer to partition, k is the length of partitions, l is the min partition element size'''
        if k < 1:
            raise StopIteration
        if k == 1:
            if n >= l:
                yield (n,)
            raise StopIteration
        for i in range(l,n+1):
            for result in partitionfunc(n-i,k-1,i):
                yield (i,)+result
    

    This generates all the partitions of n with length k with each one being in order of least to greatest.

    Just a quick note: Via cProfile, it appears that using the generator method is much faster than using falsetru's direct method, using the test function lambda x,y: list(partitionfunc(x,y)). On a test run of n=50,k-5, my code ran in .019 seconds vs the 2.612 seconds of the direct method.

    0 讨论(0)
提交回复
热议问题