Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/312.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在最大化最低权重的同时,使用因子均匀分割数字的算法_Python_Algorithm_Math - Fatal编程技术网

Python 在最大化最低权重的同时,使用因子均匀分割数字的算法

Python 在最大化最低权重的同时,使用因子均匀分割数字的算法,python,algorithm,math,Python,Algorithm,Math,给定一个数字和一系列因素,将该数字拆分为其给定因素以最大化最小权重(权重是特定因素的倍数)的最有效方法是什么 另一种说法是: Given: w1*f1 + w2*f2 + ... + wN*fN = Z Where: given f1,f2,f3...fN are ascending order factors of a given positive number Z Find: w1,w2,w3...wN which are corresponding facto

给定一个数字和一系列因素,将该数字拆分为其给定因素以最大化最小权重(权重是特定因素的倍数)的最有效方法是什么

另一种说法是:

Given:
    w1*f1 + w2*f2 + ... + wN*fN = Z

Where:
    given f1,f2,f3...fN are ascending order factors of a 
    given positive number Z

Find: w1,w2,w3...wN which are corresponding factors' non-zero positive weights and
weights being approximately evenly distributed

Example

e.g. Given: a + 2b + 4c = 32, find largest together possible a,b,c
1  2  4
a  b  c
32 00 00
00 16 00
00 00 08
08 04 04
06 05 04    <- should be the outcome of this algorithm
给定:
w1*f1+w2*f2+…+wN*fN=Z
哪里:
给定f1、f2、f3…fN是a的升序因子
给定正数Z
找到:w1,w2,w3…wN,它们是对应因子的非零正权重和
近似均匀分布的重量
例子
e、 g.给定:a+2b+4c=32,求出最大可能的a,b,c
1  2  4
a、b、c
32 00 00
00 16 00
00 00 08
08 04 04

06 05 04可能的方法:好的溶液应含有一些重量相等的部分

从可能的最大重量开始,Kmax=N div SumOfFactors
并分割剩余的重量。
如果无法拆分-减小重量并重复

这种方法试图减少问题的规模——这对于更大的总和和总和的数量很重要

例如,好的解决方案应该是

32 = K * (1 + 2 + 4) + Split_of_(32 - 7 * K)
Kmax = 32 div 7 = 4
Rest = 32 - 4 * 7 = 4
Varitants of splitting rest 4 into factors: 
4 = 4  gives weights 4 4 5
4 = 2+2  gives weights  4 6 4
4 = 2+1+1  gives weights 6 5 4  
4 = 1+1+1+1 gives weights 8 4 4     
对您来说,最好的变体是
2+1+1
(可能是具有最不同因素的变体),而我认为解决方案(未在您的示例中列出)
45
也相当不错

KMax不适用时的情况:

 120 into (2,7,11,19)  
 sum = 39, k=3, rest = 3,  it is impossible to make 3
           k=2, rest = 42, we can make partitions:
                       42=3*2+2*7+2*11, possible solution is 5,4,4,2    
                       42=2*2+2*19, possible solution is 4,2,2,4    
实现@MBo应答(在他告诉我逻辑时选择他的应答)。如果我错过了一个用例,请随意评论(我故意不考虑减少
k
,因为此函数的目的是为给定的一组因子获得最大最小权重)


谢谢,你能再举一个例子吗。。我不明白你是如何从
4 4 5
中得到
4 4 5
?你错过了这个变体:
4*1+4*2+5*4
谢谢,我知道了。。。但是想弄清楚这是一种算法还是一种基本的因式分解?当你说
1+1+1+1
时,你的意思是
(1+1)=>8+1=>4+1=>4
。这种方法可以减少问题的规模(如果可能的话)。大约1个-是的,我们已经有了
4*1+4*2+4*4
并添加了4个1以获得
8*1+4*2+4*4
谢谢,但我可能在这方面仍然很慢:(如果你能再举一个例子,一步一步地展示它,那就太好了:对于1,2,8个因子来分割一个32,我看到:1+2+8=11 Kmax=32/11=2 Rest=32%11=10,现在取最高的一个:2 7 2,这个逻辑也适用于大量的因子吗?
 120 into (2,7,11,19)  
 sum = 39, k=3, rest = 3,  it is impossible to make 3
           k=2, rest = 42, we can make partitions:
                       42=3*2+2*7+2*11, possible solution is 5,4,4,2    
                       42=2*2+2*19, possible solution is 4,2,2,4    
def evenly_weight_a_number_with_factors(number, factors):
    """
    Args:
        number (int): Number to evenly split using `factors`
        factors (list): list of ints

    >>> evenly_weight_a_number_with_factors(32, [1,2,4])
    6,5,4

        Given:
            w1*f1 + w2*f2 + ... + wN*fN = Z

        Where:
            given f1,f2,f3...fN are ascending order factors of a 
            given positive number Z

        Find: w1,w2,w3...wN which are corresponding factors' non-zero positive weights and
        weights being approximately evenly distributed

        Example

        e.g. Given: a + 2b + 4c = 32, find largest together possible a,b,c
        1  2  4
        a  b  c
        32 00 00
        00 16 00
        00 00 08
        08 04 04
        06 05 04    <- should be the outcome of this algorithm

    """
    log = logging.getLogger(evenly_weight_a_number_with_factors_logger_name)

    # function to return True if all numbers in `_factors` are factors of number `n`
    are_all_factors = lambda n, _factors: all(n % f == 0 for f in _factors)

    def weighted_sum(__weights, __factors):
        return sum([wt*factor for wt, factor in zip(__weights, __factors)])

    def add_variant_wt(__weights, i, _remainder_weight):
        old__weights = __weights[:]
        if _remainder_weight < factors[i]:
            log.warn('skipping  add_variant_wt _remainder_weight: {} < factor: {}'.format(_remainder_weight, factors[i]))
            return []

        variant_wt = _remainder_weight / factors[i]
        variant_wt_rem = _remainder_weight % factors[i]
        log.debug('add_variant_wt: weights, i, renainder_weight, variant_wt, remain: {}'
                  .format((__weights, i, _remainder_weight, variant_wt, variant_wt_rem)))
        if variant_wt_rem:
            __weights[i] += variant_wt
            if i + 1 >= len(factors):
                return add_variant_wt(__weights, i-1, variant_wt_rem)

            return add_variant_wt(__weights, i+1, variant_wt_rem)

        __weights[i] += variant_wt
        log.debug('add_variant_wt i: {} before: {} after: {}'.format(i, old__weights, __weights))
        return __weights


    assert list(sorted(factors)) == factors, "Given factors {} are not sorted".format(factors)
    assert are_all_factors(number, factors) == True, "All numbers in {} are not factors of number: {}".format(factors, number)

    sum_of_all_factors = sum(factors)
    largest_possible_weight = number / sum_of_all_factors
    remainder_weight = number % sum_of_all_factors

    variant_weight_sets = []
    tmp_weights = []
    for _ in factors:
        tmp_weights.append(largest_possible_weight)

    log.debug('tmp_weights: {} remainder_weight: {}'.format(tmp_weights, remainder_weight))
    for i, _ in enumerate(factors):
        _weights = add_variant_wt(tmp_weights[:], i, remainder_weight)
        if _weights:
            variant_weight_sets.append(_weights)

    weights = variant_weight_sets[-1]    # pick wt variance where largest factor gets the biggest weight
    log.debug('variant_weight_sets: {}'.format(variant_weight_sets))
    sum_weighted = weighted_sum(weights, factors)
    assert sum_weighted == number, "sum_weighted: {} != number: {}".format(sum_weighted, number)
    return weights
>>> evenly_weight_a_number_with_factors(32, [1,2,4])
[4, 4, 5]
>>> evenly_weight_a_number_with_factors(32, [1,2,8])
[2, 3, 3]
>>> evenly_weight_a_number_with_factors(32, [1,2,2])
[6, 6, 7]
>>> evenly_weight_a_number_with_factors(100, [1,2,4,4,100])
[0, 0, 0, 0, 1]
>>> evenly_weight_a_number_with_factors(100, [1,2,4,4])
[10, 9, 9, 9]
>>>