创建所有配对并与正确配对进行比较
首先,定义一个生成所有配对的函数,以及一个生成正确配对的函数:
def all_pairings(l):
if len(l) == 0:
return [[]]
else:
return [[(l[0],l[i])] + p for i in range(1,len(l)) for p in all_pairings(l[1:i]+l[i+1:])]
def adjacent_pairing(l):
it = iter(l)
return zip(it, it)
那么它只是一个for循环:
children = ['a1', 'a2', 'b1', 'b2', 'c1', 'c2', 'd1', 'd2']
correct_pairing = set(adjacent_pairing(children))
for pairing in all_pairings(children):
sentence = 'Found' if set(pairing) == correct_pairing else 'Not found'
print(', '.join(''.join(pair) for pair in pairing), ' -- ', sentence)
输出:
a1a2, b1b2, c1c2, d1d2 -- Found
a1a2, b1b2, c1d1, c2d2 -- Not found
a1a2, b1b2, c1d2, c2d1 -- Not found
a1a2, b1c1, b2c2, d1d2 -- Not found
...
a1d2, a2d1, b1b2, c1c2 -- Not found
a1d2, a2d1, b1c1, b2c2 -- Not found
a1d2, a2d1, b1c2, b2c1 -- Not found
洗牌
我建议在迭代之前使用random.shuffle 打乱可能的配对(否则,正确的配对总是第一个生成的配对,这有点无聊)。
import random
l = list(all_pairings(children))
random.shuffle(l)
for pairing in l:
sentence = 'Found' if set(pairing) == correct_pairing else 'Not found'
print(', '.join(''.join(pair) for pair in pairing), ' -- ', sentence)
输出:
a1a2, b1d2, b2d1, c1c2 -- Not found
a1d1, a2d2, b1c2, b2c1 -- Not found
a1b2, a2c2, b1c1, d1d2 -- Not found
...
a1b1, a2c2, b2d1, c1d2 -- Not found
a1a2, b1b2, c1c2, d1d2 -- Found
a1b2, a2c2, b1d2, c1d1 -- Not found
...
a1c2, a2d2, b1b2, c1d1 -- Not found
a1c2, a2d2, b1c1, b2d1 -- Not found
a1b1, a2b2, c1c2, d1d2 -- Not found
找到正确配对的概率
假设所有配对都是等概率的,随机挑选一对时找到正确配对的概率为 1 除以不同可能配对的总数。
有多少种不同的可能配对?
选择有序配对,其中配对的顺序很重要,每对中的两个孩子的顺序很重要,这与选择排列相同。众所周知,N! 可能有 N 子代的排列。
每个无序配对对应多少有序配对?
有 2 种可能的方式来订购每对中的 2 个孩子;因此,有2 ** (N / 2) 方法可以订购所有对的 2 个孩子。
有(N / 2)! 可能的方式来订购N / 2 对。
因此,每个配对对应于(N / 2)! * 2 ** (N / 2) 有序配对。
因此,N! / ( (N / 2)! * 2 ** (N / 2) ) 必须有 N 孩子的不同可能配对。
对于您的 8 个孩子,这是8! / (4! * 2**4) == 105。
当在所有不同的可能配对中均匀随机选择时,选择正确配对的概率是该数字的 1:
在 8 个孩子的情况下略低于 1%。
随机配对中正确配对的预期数量
让我们在所有不同的可能配对中随机选择一个配对。平均而言,该配对中有多少对是正确的?
我们可以在我们的python程序中计算每个配对中正确配对的数量:
for pairing in all_pairings(children):
nb_correct_pairs = len(set(pairing) & correct_pairing)
print(', '.join(''.join(pair) for pair in pairing), ' -- ', nb_correct_pairs)
输出:
a1a2, b1b2, c1c2, d1d2 -- 4
a1a2, b1b2, c1d1, c2d2 -- 2
a1a2, b1b2, c1d2, c2d1 -- 2
a1a2, b1c1, b2c2, d1d2 -- 2
a1a2, b1c1, b2d1, c2d2 -- 1
a1a2, b1c1, b2d2, c2d1 -- 1
a1a2, b1c2, b2c1, d1d2 -- 2
a1a2, b1c2, b2d1, c1d2 -- 1
...
a1d2, a2c1, b1d1, b2c2 -- 0
a1d2, a2c2, b1b2, c1d1 -- 1
a1d2, a2c2, b1c1, b2d1 -- 0
a1d2, a2c2, b1d1, b2c1 -- 0
a1d2, a2d1, b1b2, c1c2 -- 2
a1d2, a2d1, b1c1, b2c2 -- 0
a1d2, a2d1, b1c2, b2c1 -- 0
平均数其实很容易用数学计算出来。
让我们考虑随机配对中的一个特定孩子,例如孩子a1。孩子a1 握住双胞胎手的概率是多少?由于有N-1 其他孩子,并且根据对称性,所有孩子的可能性都相同,因此孩子a1 将握住他们双胞胎的手的概率是1/(N-1)。
当然,这适用于所有孩子,而不仅仅是a1。因此,平均而言,1/(N-1) 的孩子会握住自己双胞胎的手。既然有N 孩子,那么平均来说,N/(N-1) == 1 + 1/(N-1) 孩子会握着自己双胞胎的手。由于每对有 2 个孩子,这意味着在随机配对中平均会有 N / (2(N-1)) == (1 + 1/(N-1)) / 2 个正确的对。
在N == 8 的情况下,这意味着4/7 ≈ 0.571 每次配对都正确。
让我们通过实验验证:
l = list(all_pairings(children))
total_correct_pairs = sum(len(set(pairing) & correct_pairing) for pairing in l)
n_pairings = len(l)
expected_correct_pairs = total_correct_pairs / n_pairings
print('Expected number of correct pairs: ', expected_correct_pairs)
输出:
Expected number of correct pairs: 0.5714285714285714