Python 用预定义值填充一维空间

Python 用预定义值填充一维空间,python,c,algorithm,Python,C,Algorithm,我想用预定义的“子长度”填充长度。 假设我的子长度是: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

我想用预定义的“子长度”填充长度。 假设我的子长度是: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
def fillBuild(长度、子长度):
对于范围内的i(len(子波长)):
如果子长度[i]==长度:
产量子长度[i:i+1]
elif子长度[i]<长度:
对于fillBuild中的子结果(长度-子长度[i],子长度[i:]):
产生子长度[i:i+1]+子结果

下面是一个递归解决方案,使用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]]
顺便说一句:
fill(70、[3,4,5,6,7,10])
生成1657个可能的填充,因此您可能需要一些额外的标准来减少替代方案


一些注意事项:

  • 为了避免重复解决方案,我们将要求每种填充物的订购量不断增加

  • 关键思想是:假设要填充的长度是L,并且a1fill
    else
    块中递归调用的基本原理。(当函数调用自身时,如
    fill
    所做的那样,该函数称为递归函数。)

  • 由于
    fill
    要求
    sublength
    无重复项,且分类越来越多,我们可以使用以下前端功能来确保满足这些条件:

    def do_填充(长度、子长度): 返回填充(长度、排序(设置(子长度)))


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]
现在,使用子长度[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]]
In [4]: fill(15 - 4, [4, 5, 6, 7, 10])
Out[4]: 
[4, 7],
[5, 6]
In [5]: fill(15 - 5, [5, 6, 7, 10])
Out[5]: 
[[5, 5],
[10]]
如果现在你在所有这些填充物前面加上3,你将得到与第一组完全相同的填充物

现在考虑第II组的填充物,所有这些填充物开始于4。使用子长度[4,5,6,7,10],将其与15-4=11的填充物进行比较:

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]]
In [4]: fill(15 - 4, [4, 5, 6, 7, 10])
Out[4]: 
[4, 7],
[5, 6]
In [5]: fill(15 - 5, [5, 6, 7, 10])
Out[5]: 
[[5, 5],
[10]]
同样,如果你在所有这些填充物前面加上4,你得到的填充物正好是第二组中的填充物

您可能想知道,为什么我在上一次调用
fill
时使用[4,5,6,7,10]作为子长度,而不是[3,4,5,6,7,10]?这是因为我只感兴趣的填充物是越来越多的秩序,并开始与4。这排除了任何包含3的填充

最后,为了得到第三组中的填充物,使用子长度[5,6,7,10],为15-5=10的所有填充物预加5:

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]]
In [4]: fill(15 - 4, [4, 5, 6, 7, 10])
Out[4]: 
[4, 7],
[5, 6]
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])
。可以通过检查发现其溶液:从子长度[5,6,7,10]中只能填充一次7。递归总是以这些琐碎情况的解结束。最终的解决方案由这些琐碎的解决方案组合而成。

递归生成器函数(Python)生成
池的所有可能的子列表排列(带重复)
总计
总数:

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]]
从pprint导入pprint
def子单元列表(池,总计):
对于范围内的i(len(pool)):
如果池[i]==总计:
收益率池[i:i+1]
elif池[i]<总计:
对于sub_列表中的sub_列表(池,总计-池[i]):
收益池[i:i+1]+子清单
pprint(列表(子列表([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]]

是否要获取所有总和?所有的价值观都是积极的吗?“语言看起来像C”-不是很有帮助。我猜可能是MEL(如果您使用Maya)或MaxScript(如果您使用3DsMax)。所以您可以重复使用元素?我可以重复使用元素。我使用的C语言在胡迪尼语中是Vex。所有值均为正值。我不需要获得所有的总数。谢谢你的代码,它工作得很好。现在,对于我的使用,当我增加