这可以通过直接递归来完成。
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']