从两个集合中选择一个数字,每个集合的乘数总和等于特定总和

时间:2018-04-19 22:34:57

标签: python pandas numpy random

我有两套,比如A = {0,1,2,...,i}和B = {3,6,10,15},一个常数$ s $和一个指定数字$ n $属于自然数集。 我想找到满足a_1 * b_1 + a_2 * b_2 + \ dots + a_n * b_n> = s

的/所有组合

例如,如果s = 25,则n = 2以下每个答案都是可接受的1 * 10 + 1 * 15,2 * 10 + 1 * 6,0 + 2 * 15或4 * 3 + 2 * 6 < / p>

如果我没有第二组,那么这很容易,因为问题会减少到产生here中引入的预定和的随机分区

我应该如何在python中有效地实现它?有什么数学方法吗? 它也让我想起某种方程式,但我不确定我应该搜索什么。 我很欣赏任何提示。

编辑:对我而言,确切地说&#34; n&#34;在我的答案中的条款,并有机会其他选择。在我的例子中,四个答案中的每一个都应该有生成的机会。换句话说,我有&#34; n&#34;用他们的条款填写他们的总和等于&#34; s&#34;。抱歉不要在第一时间清除它。

1 个答案:

答案 0 :(得分:2)

可以通过直接递归来完成。

from functools import lru_cache

def find_combinations(numbers, threshold, nterms, maxcoeff, stringify=True):
    numbers = sorted(numbers, reverse=True)
    @lru_cache(None)
    def rec(k, s, n):
        if s > maxcoeff * numbers[k]:
            top = maxcoeff
            res = []
        else:
            top = (s-1) // numbers[k]
            res = [[top + 1]]
        if n > 1 and k < len(numbers)-1:
            for j in range(top, -1, -1):
                res.extend([[j, *subres] for subres in rec(
                    k+1, s-j*numbers[k], n-(j!=0))])
        return res
    if stringify:
        return [' + '.join(f'{c}\u2a2f{n}' for c, n in zip(sol, numbers) if c)
                for sol in rec(0, threshold, nterms)]
    else:
        return rec(0, threshold, nterms)

print(find_combinations({3, 6, 10, 15}, 25, 2, 2))

打印:

['2⨯15', '1⨯15 + 1⨯10', '2⨯10 + 1⨯6']

更新:允许numbers多次出现(这些被混为一谈,基本上maxcoeff乘以每个数字的出现次数):

def find_combinations_with_replacement(numbers, threshold, nterms, maxcoeff,
                                       stringify=True):
    numbers = sorted(numbers, reverse=True)
    @lru_cache(None)
    def rec(k, s, n):
        if s > maxcoeff * numbers[k] * n:
            return []
        top = (s-1) // numbers[k]
        res = [[top + 1]]
        if n > 1 and k < len(numbers)-1:
            for j in range(top, -1, -1):
                res.extend([[j, *subres] for subres in rec(
                    k+1, s-j*numbers[k], n - (j-1) // maxcoeff - 1)])
        return res
    if stringify:
        return [' + '.join(f'{c}\u2a2f{n}' for c, n in zip(sol, numbers) if c)
                for sol in rec(0, threshold, nterms)]
    else:
        return rec(0, threshold, nterms)

print(find_combinations_with_replacement({3, 6, 10, 15}, 25, 4, 1))

打印:

['2⨯15', '1⨯15 + 1⨯10', '1⨯15 + 2⨯6', '1⨯15 + 1⨯6 + 2⨯3', '3⨯10', '2⨯10 + 1⨯6', '2⨯10 + 2⨯3', '1⨯10 + 3⨯6', '1⨯10 + 2⨯6 + 1⨯3']