生成组合而不是排列。怎么样?

时间:2013-10-19 16:56:39

标签: python-3.x combinatorics

经过一些在线研究后,似乎很多人倾向于将组合与排列混淆。

示例:

强力球项目有5个数字1 - 59,最后一个强力球数为1 - 35。

问题:

与Excel函数COMBIN()类似,无论内部顺序如何,如何生成一组或一部分项的所有组合?

组合与Permutaions不同,内部顺序非常重要。

前5: 59 x 58 x 57 x 56 x 55 = 5,006,386

强力球: 5,006,386 X 35 = 175,223,510

我希望你帮我生成前5个组合,然后再用First 5 + Powerball创建一个组合。

3 个答案:

答案 0 :(得分:3)

正如在其他答案和评论中指出的那样,为了生成“前5”的所有组合,您可以使用itertools.combinations

first5 = itertools.combinations(range(1, 59+1), 5)

并且对于那些产品和“强力球”号码,请使用itertools.product

first5andPowerball = itertools.product(first5, range(1, 35+1))

这两个都是 generator 对象。要将它们变为实际列表,只需使用list函数,例如list(first5),但这些列表将巨大,我不知道您可以为它们使用什么

如果你想获得一个随机组合(比如抽奖图),那么不使用combinations,而是shuffle数字和选择前五个,就像洗牌一副牌并从前五个中选出前五个:

numbers = range(1, 59+1)
random.shuffle(numbers)
first5 = numbers[:5]
bonus = random.randint(1, 35)
print first5, bonus

甚至更简单,使用sample(感谢@dansalmo提示)

first5 = random.sample(range(1, 59+1), 5)

答案 1 :(得分:2)

以下是一个说明性示例,说明如何列出仅选择6个数字的游戏的组合:

>>> from itertools import combinations
>>> list(combinations(range(1, 6+1), 5))
[(1, 2, 3, 4, 5), (1, 2, 3, 4, 6), (1, 2, 3, 5, 6), (1, 2, 4, 5, 6),
(1, 3, 4, 5, 6), (2, 3, 4, 5, 6)]

以下是“First 5”组合数量的示例:

>>> len(list(combinations(range(1, 59+1), 5)))
5006386

如果您想要整个列表,只需删除len()功能。

要使用强力球为5的Pick 2 of 4获得所有组合,需要使用两种组合的Cartiesian产品:

>>> list((x,y) for x in combinations(range(1,4+1),2) for y in range(1,5+1))
[((1, 2), 1), ((1, 2), 2), ((1, 2), 3), ((1, 2), 4), ((1, 2), 5), ((1, 3), 1), ((1, 3), 2), ((1, 3), 3), ((1, 3), 4), ((1, 3), 5), ((1, 4), 1), ((1, 4), 2), ((1, 4), 3), ((1, 4), 4), ((1, 4), 5), ((2, 3), 1), ((2, 3), 2), ((2, 3), 3), ((2, 3), 4), ((2, 3), 5), ((2, 4), 1), ((2, 4), 2), ((2, 4), 3), ((2, 4), 4), ((2, 4), 5), ((3, 4), 1), ((3, 4), 2), ((3, 4), 3), ((3, 4), 4), ((3, 4), 5)]

即使数量很少,您也可以看到组合的增长速度!

获得所有强力球组合将是:

>>> list((x,y) for x in combinations(range(1,59+1),2) for y in range(1,35+1))

但它对我的系统来说太大了。

添加DSM的评论:

使用产品创建生成器:

from itertools import combinations, product
cgen = product(combinations(range(1,59+1),5), range(1,35+1))
for c in cgen:
    #write c to file

或者您可以在写入文件之前收集一些数量的c。

每个组合都是以下形式的元组:((1, 2, 3, 4, 5), 1)

答案 2 :(得分:1)

根据这个问题“是否有可能针对该范围内的所有可能选择运行一个5的中奖选择列表,并找出它的索引?”在@ tobias_k的回答评论中:

>>> from itertools import combinations
>>> all = list(combinations(range(1, 59+1), 5))
>>> all.index((1, 2, 3, 4, 59))
54
>>> all.index((32, 42, 43, 54, 59))
4922705

以上是可行的,但索引查找时间在列表末尾变得更长(<1秒)。尝试创建一个dict会导致内存错误。

当然可以创建一个公式来派生索引而不创建列表。你应该把它作为另一个问题发布。