Python 3.x 生成组合而不是排列。怎么用?

Python 3.x 生成组合而不是排列。怎么用?,python-3.x,combinatorics,Python 3.x,Combinatorics,经过一些在线研究,似乎很多人倾向于混淆组合和排列 例如: 强力球系列有5个数字1-59和最后一个强力球数字1-35 问题: 与Excel函数combi()类似,如何生成项目集或子集的所有组合,而不考虑内部顺序 组合不同于置换,置换的内部顺序是重要的 前5项: 59 x 58 x 57 x 56 x 55=5006386 力量球: 5006386 X 35=175223510 我希望您能帮助我生成前5个组合,然后使用前5个+Powerball生成一个单独的组合。下面是一个示例,演示如何列出仅选择6

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

例如:

强力球系列有5个数字1-59和最后一个强力球数字1-35

问题:

与Excel函数combi()类似,如何生成项目集或子集的所有组合,而不考虑内部顺序

组合不同于置换,置换的内部顺序是重要的

前5项: 59 x 58 x 57 x 56 x 55=5006386

力量球: 5006386 X 35=175223510


我希望您能帮助我生成前5个组合,然后使用前5个+Powerball生成一个单独的组合。

下面是一个示例,演示如何列出仅选择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)]
以下是“前5个”组合数的示例:

如果需要整个列表,只需删除
len()
函数即可

要获得动力球为5的4选2的所有组合,需要使用两种组合的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)]
您可以看到,即使使用较小的数字,组合的增长速度也是如此之快

要获得所有Powerball组合,请执行以下操作:

>>> 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)

正如在另一个答案以及注释中指出的,要生成“前5个”的所有组合,您可以使用
itertools。组合

first5 = itertools.combinations(range(1, 59+1), 5)
对于这些和“Powerball”编号的乘积,请使用
itertools.product

first5andPowerball = itertools.product(first5, range(1, 35+1))
这两个都是生成器对象。要将它们转换为实际的列表,只需使用
list
功能,例如
list(first5)
,但这些列表将是巨大的,我不知道您对它们有什么用处

如果您只想获得一个随机组合(如抽奖),则不使用
组合
,而是
洗牌
数字并选择前五个,就像洗牌一副牌并从顶部选择前五个:

numbers = range(1, 59+1)
random.shuffle(numbers)
first5 = numbers[:5]
bonus = random.randint(1, 35)
print first5, bonus
或者更简单,使用
sample
(感谢@dansalmo的提示)

根据@tobias_k回答评论中的问题“是否有可能针对该范围内所有可能的选秀,运行一个5个选秀的获奖名单,并找出其索引?”

>>> 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会导致我的内存错误


当然,应该可以创建一个公式来推导索引,而无需创建列表。你应该把它作为另一个问题发布。

你试过什么?你在找算法还是库?如果是后者,请查看
itertools
。我现在正在使用黑莓手机。。。我想应该是itertools。我只是希望得到一个样本。我指的是你的陈述“我希望你帮助我生成前5个组合”。你这话到底是什么意思?如果您想要所有的组合,请列出(itertools.combines(范围(1,59+1),5)),但最好确保您有足够的RAM…@tobias_k,术语“前5个”是彩票的营销术语。维尼不想要前五个组合,他想要的是“前五个”和“强力球”游戏的所有组合(或者他想要计算有多少个组合)。仍然不完全清楚你需要这个列表做什么。也许有一种方法比为你真正想做的事情生成整个列表更简单?我认为在“前5个”+“Powerball”案例中使用
product
,例如
product(组合(范围(1,59+1),5),范围(1,35+1))
。然后你可以做
sum(prod..中p的1)
并在不具体化列表的情况下计算它们。这是我创建的一个单词列表生成器,它可以写入文件。由于您指出的RAM问题,如何将您的代码添加到现有代码中?
random.sample(范围(1,59+1),5),random.randint(1,35)
Ok。那么,是否有可能对该范围内所有可能的选秀结果运行一个5个中奖选秀结果的列表,并找出它的索引?@Vini你的意思是,你有一个按顺序生成的所有数字的列表(从(1,2,3,4,5,1)等开始),并且你想确定(34,58,1,14,7,4)在该列表中的位置?是的!这只是通过索引分析中奖号码的另一种方法。或者!如果我可以将每个组合插入一个MySQL数据库,主键将用作索引。
first5 = random.sample(range(1, 59+1), 5)
>>> 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