繁体   English   中英

列出所有组合但有限制

[英]List all combinations but with restriction

我找到了列出以k个元素为一组的n个元素的所有可能组合的方法。 从数学上看,数字很容易:n!/(k!*(nk)!),使用itertools的python代码非常简单:

>>> import itertools
>>> a = [1,2,3,4]
>>> list(itertools.combinations(a,3))
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]

但是如何实现这样的限制:仅列出共有m个元素的组? 因此,在前面的示例中,对于m = 1,结果应为:

[(1, 2, 3)]

有5个元素且m = 1:

>>> b=[1,2,3,4,5]
>>> list(itertools.combinations(b,3))
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]

所以我的结果是:

[(1, 2, 3), (1, 4, 5)]

考虑到只有m个人可以在结果组中重复,此问题的实际应用是如何对人员进行分组。 想法是找到与不同的人在一起的团体,避免“朋友”的团体。 想象一下,这是重复几天的学校活动,我们要确保避免人们尽可能多地与他人重复。

可以使用for循环将第一个组合与其他组合进行比较(使用设置的交集函数"&" ):

def getsets(a, n):              # FUNCTION FOR THIS PURPOSE
    combos = list(itertools.combinations(a,n))  # GET ALL COMBINATIONS
    print(combos[0])            # PRINT FIRST COMBINATION
    for i in combos[1:]:        # FOR EACH OF REST
        if len(set(combos[0]) & set(i)) == 1:       # IF ONLY 1 ITEM COMMON WITH INITIAL
            print(i)            # PRINT IT

测试:

getsets([1,2,3,4], 3)
print("---------")
getsets([1,2,3,4,5], 3)

输出:

(1, 2, 3)   # INITIAL SET ONLY
---------
(1, 2, 3)   # INITIAL SET
(1, 4, 5)   # ONLY '1' IS COMMON WITH FIRST SET
(2, 4, 5)   # ONLY '2' IS COMMON WITH FIRST SET
(3, 4, 5)   # ONLY '3' IS COMMON WITH FIRST SET
{1, 2, 3}   # ONLY '4' IS COMMON WITH FIRST SET

您可以使用for循环:

m = 1
combos = list(itertools.combinations(a,3))
result = []
for combo in combos:
    if result:
        if all([sum([1 for item in combo if item in tup]) == 1 for tup in result]):
            result.append(combo)
    else:
        result.append(combo)
result
#[(1, 2, 3), (1, 4, 5)]

这样,您将能够控制相互成员的数量并获得所需的输出。

看来,您得到的结果在逻辑上是这样的:

a = range(1,6)
shared_elem_count = 1
group_count = 3

combinations = itertools.combinations(a, group_count)
results = []

for combination in combinations:
    res_union = set().union(*results)
    intersection = set(combination).intersection(res_union)
    if len(intersection) <= shared_elem_count:
        results.append(combination)

就像在您的示例中一样,元组与其他任何可用元素之间共享的共有m个以上。 但是正如评论中指出的那样,该解决方案严格遵循操作顺序。 第一个元组确定可接受的下一个元组。

请注意,您在评论中说的是一个更广泛的问题:将n个人归为不超过m共同点的k群体将提供比我们没有的解决方案多得多的解决方案过滤掉”。 例如,您已经指出,对于m = 1a = (1,2,3,4,5)解决方案是:

(1,2,3),(1,4,5)

...但是实际上还有更多解决方案,例如:

(2,3,4),(1,2,5)
(3,4,5),(1,2,3)
(1,4,5),(2,3,4)

因此,我不能完全确定过滤组合是否是解决问题的正确方法(不过,尚不清楚您实际上想实现什么目标,所以知道)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM