无序组合,更换数量有限



我必须列出重复次数有限的无序组合 即对于给定的唯一元素列表,card_set创建长度combo_len的所有组合,元素最多重复 repeat_limit 次

下面的代码适用于 combo_len = 3 和 repeat_limit = 2,card_set = 范围(5(

注意我需要无序组合。 即(0,0,1(和(0,1,0(相同,因此下面的解决方案链接不能满足我的条件

这篇文章告诉我如何获得有限重复的矿石组合

import itertools
import pprint
card_set = list(range(5))
a = sorted(set(itertools.combinations_with_replacement(card_set,3)))
neg = [(i,i,i) for i in card_set]
b = set(a) - set(neg)
print('a###')
pprint.pprint(a)
print('b###')
pprint.pprint(b)

上面的代码给了我一个无序组合,有有限的 2 个重复,即 neg 包含不需要的重复 (0,0,0( (1,1,1( 等 所以b = set(a) - set(neg)给我所需的套装

对于 combo_len = 3 和 repeat_limit = 2,上述代码有效。如何为 range(13( 创建代码 combo_len = 7 和 repeat_limit = 4

输出:

a###
[(0, 0, 0),
(0, 0, 1),
(0, 0, 2),
(0, 0, 3),
(0, 0, 4),
(0, 1, 1),
(0, 1, 2),
(0, 1, 3),
(0, 1, 4),
(0, 2, 2),
(0, 2, 3),
(0, 2, 4),
(0, 3, 3),
(0, 3, 4),
(0, 4, 4),
(1, 1, 1),
(1, 1, 2),
(1, 1, 3),
(1, 1, 4),
(1, 2, 2),
(1, 2, 3),
(1, 2, 4),
(1, 3, 3),
(1, 3, 4),
(1, 4, 4),
(2, 2, 2),
(2, 2, 3),
(2, 2, 4),
(2, 3, 3),
(2, 3, 4),
(2, 4, 4),
(3, 3, 3),
(3, 3, 4),
(3, 4, 4),
(4, 4, 4)]

b###
{(0, 0, 1),
(0, 0, 2),
(0, 0, 3),
(0, 0, 4),
(0, 1, 1),
(0, 1, 2),
(0, 1, 3),
(0, 1, 4),
(0, 2, 2),
(0, 2, 3),
(0, 2, 4),
(0, 3, 3),
(0, 3, 4),
(0, 4, 4),
(1, 1, 2),
(1, 1, 3),
(1, 1, 4),
(1, 2, 2),
(1, 2, 3),
(1, 2, 4),
(1, 3, 3),
(1, 3, 4),
(1, 4, 4),
(2, 2, 3),
(2, 2, 4),
(2, 3, 3),
(2, 3, 4),
(2, 4, 4),
(3, 3, 4),
(3, 4, 4)}

您可以使用collections模块中的Counter类来查找给定元组中每个值的重复次数。对于每个元组,对其进行Counter并检查重复的最大值。如果该最大值足够小,则接受元组;否则,拒绝它。

这是执行此操作的例程。如果我有更多的时间,我会把它美化。

小心这个例程。对于给定的值range_size=13, combo_len=7, repeat_limit=4,结果是一个长度为 49,205 的列表。

from collections import Counter
from itertools import combinations_with_replacement
def unordered_combinations_with_limited_replacements(
range_size, combo_len, repeat_limit):
return [t for t in combinations_with_replacement(range(range_size), combo_len)
if max(Counter(t).values()) <= repeat_limit]
print(unordered_combinations_with_limited_replacements(5, 3, 2))
print(len(unordered_combinations_with_limited_replacements(13, 7, 4)))

以下是打印输出:

[(0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 3), (0, 3, 4), (0, 4, 4), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), (3, 3, 4), (3, 4, 4)]
49205

首先,示例代码中使用的neg仅在repeat_limit等于combo_length时才有效。

所以我搜索了一些可以计算列表中不同元素的东西,并在collections模块中提出了Counter。下一步是使用简单的for循环循环遍历itertools.combinations_with_replacement创建的所有元素。如果Counter对象中最常见的元素高于您的repeat_limit,请从列表中删除该元素。

此代码适用于每个范围、combo_length和repeat_limit:

import itertools
from collections import Counter
def getUnorderedCombo(list_range, combo_len, repeat_lim):
card_set = list(range(list_range))
a = list(set(itertools.combinations_with_replacement(card_set,combo_len)))
i = 0
while i < len(a):
c = Counter(a[i])
if c.most_common(1)[0][1] > repeat_lim:
del a[i]
i -= 1
i += 1
return set(a)

最新更新