在给定的抛硬币次数中找到特定数量头和尾的所有组合

3

我想要计算给定硬币抛掷次数的所有可能组合,目前以10作为测试用例。我认为这是笛卡尔积,但我上一次上数学课已经很久了。不过,我的目标是先计算最有可能的分布。这是我开始使用的代码:

import itertools
for x in itertools.product(['H','T'],repeat=10):
    print(x)

这将给我10个硬币翻转的所有可能组合。但第一个结果是全正面朝上,这不太可能发生。我的想法是从均匀分布开始,即5个正面朝上和5个反面朝上的所有组合,然后继续4正6反(加上反面朝上的相反情况),3正7反(加上反面朝上的相反情况)等等。但是,我不确定是否可以使用itertools或其他内置模块或模块组合来实现这一点。
如果我使用以下内容:
import itertools
for x in itertools.permutations(['H','H','H','H','H','T','T','T','T','T']):
    print(x)

然后会出现很多重复,因为它将每个'H'和'T'都视为独特的。有关如何解决这个问题的建议吗?

2个回答

2

通过导入multiset_permutations,可以计算252个排列组合(即10!/5!/5!)。

>>> from sympy.utilities.iterables import multiset_permutations
>>> for item in multiset_permutations(['H','H','H','H','H','T','T','T','T','T']):
    print(item)

['H', 'H', 'H', 'H', 'H', 'T', 'T', 'T', 'T', 'T']
['H', 'H', 'H', 'H', 'T', 'H', 'T', 'T', 'T', 'T']
['H', 'H', 'H', 'H', 'T', 'T', 'H', 'T', 'T', 'T']
['H', 'H', 'H', 'H', 'T', 'T', 'T', 'H', 'T', 'T']
['H', 'H', 'H', 'H', 'T', 'T', 'T', 'T', 'H', 'T']
['H', 'H', 'H', 'H', 'T', 'T', 'T', 'T', 'T', 'H']
['H', 'H', 'H', 'T', 'H', 'H', 'T', 'T', 'T', 'T']
['H', 'H', 'H', 'T', 'H', 'T', 'H', 'T', 'T', 'T']
['H', 'H', 'H', 'T', 'H', 'T', 'T', 'H', 'T', 'T']
['H', 'H', 'H', 'T', 'H', 'T', 'T', 'T', 'H', 'T']
['H', 'H', 'H', 'T', 'H', 'T', 'T', 'T', 'T', 'H']
['H', 'H', 'H', 'T', 'T', 'H', 'H', 'T', 'T', 'T']
['H', 'H', 'H', 'T', 'T', 'H', 'T', 'H', 'T', 'T']
['H', 'H', 'H', 'T', 'T', 'H', 'T', 'T', 'H', 'T']
['H', 'H', 'H', 'T', 'T', 'H', 'T', 'T', 'T', 'H']
...
['T', 'T', 'T', 'H', 'H', 'T', 'H', 'T', 'H', 'H']
['T', 'T', 'T', 'H', 'H', 'T', 'T', 'H', 'H', 'H']
['T', 'T', 'T', 'H', 'T', 'H', 'H', 'H', 'H', 'T']
['T', 'T', 'T', 'H', 'T', 'H', 'H', 'H', 'T', 'H']
['T', 'T', 'T', 'H', 'T', 'H', 'H', 'T', 'H', 'H']
['T', 'T', 'T', 'H', 'T', 'H', 'T', 'H', 'H', 'H']
['T', 'T', 'T', 'H', 'T', 'T', 'H', 'H', 'H', 'H']
['T', 'T', 'T', 'T', 'H', 'H', 'H', 'H', 'H', 'T']
['T', 'T', 'T', 'T', 'H', 'H', 'H', 'H', 'T', 'H']
['T', 'T', 'T', 'T', 'H', 'H', 'H', 'T', 'H', 'H']
['T', 'T', 'T', 'T', 'H', 'H', 'T', 'H', 'H', 'H']
['T', 'T', 'T', 'T', 'H', 'T', 'H', 'H', 'H', 'H']
['T', 'T', 'T', 'T', 'T', 'H', 'H', 'H', 'H', 'H']

编辑:楼主提到对于某些情况可能会超过递归限制。下面是一些计算,果然,多重集合排列的项数可能会变得非常大。我想你需要知道你的集合有多大。

>>> from math import comb
>>> '{:,}'.format(comb(50,25))
'126,410,606,437,752'
>>> '{:,}'.format(comb(20,10))
'184,756'
>>> '{:,}'.format(comb(10,5))
'252'

唯一的问题是multiset_permutations是递归的,对于大型集合会失败:RecursionError: maximum recursion depth exceeded in comparison - user2328273
@user2328273 感谢您的更新,虽然我想不出可能的替代方案。 - Chris Charley

1
这是你要找的吗?
from itertools import combinations_with_replacement

for comb in combinations_with_replacement(['T', 'H'], r=10):
    print(comb)

输出:

('T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T')
('T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'H')
('T', 'T', 'T', 'T', 'T', 'T', 'T', 'T', 'H', 'H')
('T', 'T', 'T', 'T', 'T', 'T', 'T', 'H', 'H', 'H')
('T', 'T', 'T', 'T', 'T', 'T', 'H', 'H', 'H', 'H')
('T', 'T', 'T', 'T', 'T', 'H', 'H', 'H', 'H', 'H')
('T', 'T', 'T', 'T', 'H', 'H', 'H', 'H', 'H', 'H')
('T', 'T', 'T', 'H', 'H', 'H', 'H', 'H', 'H', 'H')
('T', 'T', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H')
('T', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H')
('H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H', 'H')

这并不是OP所描述的功能。 - Ann Zen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接