我想用预定义的" subLengths"来填充长度。 比方说我的subLength是:3,4,5,6,7,10。 要填写15的长度,我可以使用" 10 + 5" ," 3 + 4 + 3 + 5" " 7 + 4 + 4" " 7 + 5 + 3" .... 我怎么能得到这些结果中的一个数组呢? 更好:我怎么能得到一个数组好几个好结果?我的最大长度是70,我想要获得这个值的所有好结果可能会很费时间。
我是一名3D艺术家,我的编码技巧很有限,我只是不知道如何处理这个问题。我可以使用Python或类似C的语言。
此代码似乎适用于我的软件:
def fillBuild(length, subLengths):
for i in range(len(subLengths)):
if subLengths[i] == length:
yield subLengths[i:i + 1]
elif subLengths[i] < length:
for subResult in fillBuild(length - subLengths[i] ,subLengths[i:] ):
yield subLengths[i:i + 1] + subResult
答案 0 :(得分:0)
这是一个使用Python 2.7的递归解决方案:
def fill(length, sublengths):
# IMPORTANT: this function will produce INCORRECT RESULTS if sublengths
# is not a list of unique integers sorted increasingly.
fillings = []
for i, sublength in enumerate(sublengths):
if sublength > length:
# if sublength is greater than length, there are no more allowable
# fillings (because sublengths are unique and are sorted
# increasingly), so we return the fillings collected so far;
return fillings
elif sublength == length:
# if sublength is exactly equal to length, then only one filling is
# possible, namely [sublength]; we append this filling to the
# fillings;
fillings.append([sublength])
else:
# we generate all the fillings that begin with sublength by
# prepending sublength to all the allowable fillings of
# (length - sublength), which we obtain by making a recursive call.
fillings.extend([[sublength] + subresult
for subresult in
fill(length - sublength, sublengths[i:])])
示例:
In [2]: fill(15, [3, 4, 5, 6, 7, 10])
Out[2]:
[[3, 3, 3, 3, 3],
[3, 3, 3, 6],
[3, 3, 4, 5],
[3, 4, 4, 4],
[3, 5, 7],
[3, 6, 6],
[4, 4, 7],
[4, 5, 6],
[5, 5, 5],
[5, 10]]
BTW:fill(70, [3, 4, 5, 6, 7, 10]))
产生了1657种可能的填充物,因此您可能需要一些额外的标准来减少替代品。
一些注意事项:
为了避免重复解决方案,我们将要求逐步订购每个灌装;
关键思想是:假设要填充的长度是 L ,而 a 1 &lt; a 2 &lt; ......&lt; a n 是可用的sublengths。要找到以 1 开头的 L 的所有可能填充,等于预先 a 1 到 L 的所有填充 - a 1 。这是else
fill
块中递归调用的基本原理。 (当函数调用自身时,如fill
所做的那样,该函数被称为递归。)
由于fill
要求sublengths
没有重复项并且排序越来越多,我们可以使用以下前端函数来确保满足这些条件:
def do_fill(长度,sublengths): 返回填充(长度,排序(设置(sublengths)))
( NB:下面是对代码执行操作的相当详细的解释。如果您已经理解了代码,则可以安全地跳过本文的其余部分。)
为了更好地了解正在发生的事情,请回到上面的示例,然后根据第一个问题对解决方案进行分组。你会得到以下三组:
# group I
[3, 3, 3, 3, 3]
[3, 3, 3, 6]
[3, 3, 4, 5]
[3, 4, 4, 4]
[3, 5, 7]
[3, 6, 6]
# group II
[4, 4, 7]
[4, 5, 6]
# group III
[5, 5, 5]
[5, 10]
现在,使用sublengths [3,4,5,6,7,10]比较组I中的填充物,其中所有填充物均以3开头,填充物为15-3 = 12:
In [3]: fill(15 - 3, [3, 4, 5, 6, 7, 10])
Out[3]:
[[3, 3, 3, 3],
[3, 3, 6],
[3, 4, 5],
[4, 4, 4],
[5, 7],
[6, 6]]
如果现在你在所有这些填充物前面加3,你就可以得到第I组的填充物。
现在考虑组II中的填充物,所有填充物都以4开始。使用sublengths [4,5,6,7,10]将它们与15-4 = 11的填充物进行比较:
In [4]: fill(15 - 4, [4, 5, 6, 7, 10])
Out[4]:
[4, 7],
[5, 6]
同样,如果你在所有这些填充物前面加4,你就可以得到第II组中的填充物。
您可能想知道,为什么我使用[4,5,6,7,10]作为上次fill
的最后一次调用的次要长度,而不是[3,4,5,6,7, 10]?这是因为我只对那些越来越有序且以4开头的填充物感兴趣。这排除了任何包含3的填充物。
最后,为了获得第III组的填充物,使用sublengths [5,6,7,10],将所有填充物的前置5分为15 - 5 = 10:
In [5]: fill(15 - 5, [5, 6, 7, 10])
Out[5]:
[[5, 5],
[10]]
如果您如此倾向,可以对每个子组重复相同的分析。例如,您可以根据他们的第一个元素对fill(15 - 3, [3, 4, 5, 6, 7, 10])
生成的填充进行分组;你会得到4组:
[3, 3, 3, 3]
[3, 3, 6]
[3, 4, 5]
[4, 4, 4]
[5, 7]
[6, 6]
这些组分别通过将3,4,5或6分别添加到
生成的填充物中获得。fill((15 - 3) - 3, [3, 4, 5, 6, 7, 10])
fill((15 - 3) - 4, [ 4, 5, 6, 7, 10])
fill((15 - 3) - 5, [ 5, 6, 7, 10])
fill((15 - 3) - 6, [ 6, 7, 10])
上面的分析只是“手动”完成了fill
函数的作用。
需要注意的一点是,每次递归调用时,问题都会变得更简单。
例如,在生成填充[3,5,7]的过程中,对fill
的以下调用已执行:
fill(15, [3, 4, 5, 6, 7, 10]) = fill(15, [3, 4, 5, 6, 7, 10])
fill(15 - 3, [3, 4, 5, 6, 7, 10]) = fill(12, [3, 4, 5, 6, 7, 10])
fill(15 - 3 - 5, [ 5, 6, 7, 10]) = fill( 7, [ 5, 6, 7, 10])
请特别注意最后一个fill(7, [5, 6, 7, 10])
。人们可以通过检查发现它的解决方案:只有一次填充7可以从子长度[5,6,7,10]。递归总是以这些微不足道的案例的解决方案结束。最终的解决方案来自这些微不足道的解决方案。
答案 1 :(得分:0)
递归生成器函数(Python)生成pool
加起来total
的所有可能的子列表排列(重复):
from pprint import pprint
def sub_lists(pool, total):
for i in range(len(pool)):
if pool[i] == total:
yield pool[i:i + 1]
elif pool[i] < total:
for sub_list in sub_lists(pool, total - pool[i]):
yield pool[i:i + 1] + sub_list
pprint(list(sub_lists([3, 4, 5, 6, 7, 10], 15)))
[[3, 3, 3, 3, 3],
[3, 3, 3, 6],
[3, 3, 4, 5],
[3, 3, 5, 4],
[3, 3, 6, 3],
[3, 4, 3, 5],
[3, 4, 4, 4],
[3, 4, 5, 3],
[3, 5, 3, 4],
[3, 5, 4, 3],
[3, 5, 7],
[3, 6, 3, 3],
[3, 6, 6],
[3, 7, 5],
[4, 3, 3, 5],
[4, 3, 4, 4],
[4, 3, 5, 3],
[4, 4, 3, 4],
[4, 4, 4, 3],
[4, 4, 7],
[4, 5, 3, 3],
[4, 5, 6],
[4, 6, 5],
[4, 7, 4],
[5, 3, 3, 4],
[5, 3, 4, 3],
[5, 3, 7],
[5, 4, 3, 3],
[5, 4, 6],
[5, 5, 5],
[5, 6, 4],
[5, 7, 3],
[5, 10],
[6, 3, 3, 3],
[6, 3, 6],
[6, 4, 5],
[6, 5, 4],
[6, 6, 3],
[7, 3, 5],
[7, 4, 4],
[7, 5, 3],
[10, 5]]