首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >创建唯一的组合,而不考虑子集大小

创建唯一的组合,而不考虑子集大小
EN

Stack Overflow用户
提问于 2022-02-06 10:36:01
回答 2查看 123关注 0票数 0

我正在做一个项目,它需要在Python中获得唯一的组合,而不管子集大小如何。

假设我有一个大小为[1,2,2,3,4,5]的列表,大小界为8。我想要有所有元素且不重复的组合,使得每个组合的和应该小于或等于8。另一个限制是,和的界的减法应该是最小的。

例如,在这种情况下,答案应该是[5,3] [4,2,2] [3,1],这样,8的总浪费将是4,即(3+1)-8=4。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-02-06 13:48:06

您可以使用递归函数“蛮力”包装组合,并从这些组合中获得最佳匹配:

代码语言:javascript
复制
def pack(sizes,bound,subset=[]):
    if not sizes:                   # all sizes used
        yield [subset]              # return current subset
        return    
    if sizes and not subset:           # start new subset             
        i,m = max(enumerate(sizes),key=lambda s:s[1])
        subset = [m]                   # using largest size
        sizes  = sizes[:i]+sizes[i+1:] # (to avoid repeats)
    used = sum(subset)              
    for i,size in enumerate(sizes):    # add to current subset
        if subset and size>subset[-1]: # non-increasing order
            continue                   # (to avoid repeats)
        if used + size <= bound:
            yield from pack(sizes[:i]+sizes[i+1:],bound,subset+[size])
    if sizes:
        for p in pack(sizes,bound): # add more subsets
            yield [subset,*p]


def bestFit(sizes,bound):
    packs = pack(sizes,bound)
    return min(packs,key = lambda p : bound*len(p)-sum(sizes))

产出:

代码语言:javascript
复制
for p in pack([1,2,3,4,5],8):
    print(p,8*len(p)-sum(map(sum,p)))

[[5, 1], [4], [3, 2]] 9
[[5, 2, 1], [4, 3]] 1
[[5, 2], [4, 3, 1]] 1
[[5, 2], [4], [3, 1]] 9
[[5, 3], [4, 2, 1]] 1
[[5, 3], [4], [2, 1]] 9
[[5], [4, 1], [3, 2]] 9
[[5], [4, 2], [3, 1]] 9
[[5], [4, 3], [2, 1]] 9
[[5], [4], [3, 2, 1]] 9
[[5], [4], [3], [2, 1]] 17

print(*bestFit([1,2,3,4,5],8))
# [5, 2, 1] [4, 3]

print(*bestFit([1,2,3,4,5,6,7,8,9],18))
# [9, 1] [8, 4, 3, 2] [7, 6, 5]

当您的大小列表变得更大时,这将以指数方式花费更长的时间,但是如果您只有非常小的输入,这可能就足够了。

票数 0
EN

Stack Overflow用户

发布于 2022-02-06 10:47:32

您可能需要类似于itertools.combinations的东西,这将使您在给定长度的子列表中提供所有可能的元素组合,而没有重复的元素。

如果您想了解更多关于函数combinations的信息,我建议您也阅读this

像这样的事情应该有效:

代码语言:javascript
复制
for i in range(8//min(myList)):
    for j in itertools.permutations(myList, i):
        if sum(j) == 8:
            print(j)

这样,您就可以得到myList的所有组合,并打印元素之和为8的那些组合。

这样的函数可能是有用的:

代码语言:javascript
复制
def permutationsWithSum(myList: list[int], n: int):
    for i in range(n//min(myList)):
        for j in itertools.permutations(myList, i):
            if sum(j) == n:
                yield j
票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71006302

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档