NonTransitive Dice之我探
前些天在网上突然看到NonTransitiveDice,也就是非传递性骰子。它们的面值不是规则的1~6,而是可以重复,当然其面值也不只到6而已。其特性是非传递的,也即若A胜B,B胜C,则A不一定胜C,可以做到C胜A。比如下面的三个骰子:
A :2, 2, 4, 4, 9, 9
B :1, 1, 6, 6, 8, 8
C :3, 3, 5, 5, 7, 7
通过概率的计算,可以证明,A胜B的概率为20/36,B胜C的概率和C胜A的概率都是20/36。
我希望通过程序来寻找这种非传递的骰子。还是使用python比较方便,但我不使用穷举法,因为当我需要寻找多个骰子的时候,穷举法的解空间太大,所以我还是进行一定次数的随机尝试吧,当然两次运行程序得到的结果可能不同。
1
首先,我需要一个函数来生成骰子的各个面,面值是从已知的数值范围内随机选择的,所以先定义面值取值列表:
#!/usr/bin/python
#-*- coding:utf-8 -*-
#FileName : dice.py
importrandom
'''
计算非传递性骰子的胜率
'''
DiceFace= range(1, 7)
这里设定面值为1~6.随机生成面值的函数(v1.0)如下:
# GenerateDie v1.0
defGenerateDie(facenum):
'''生成骰子的各个面值,共facenum面'''
d= []
i= 0
whilei < facenum:
v= random.choice(DiceFace)
d.append(v)
i+= 1
d.sort()
returnd
从diceFace中随机选择facenum个值来生成一个骰子的面值。
2
其次,我还需要一个函数来计算骰子A对骰子B的胜率,但为了获得更全面的信息,该函数还应该返回负率及和率。函数如下:
# countLtEqGt v1.0
defcountLtEqGt(num, L):
'''计算num比L中小、等、大的个数'''
cl= 0
ce= 0
cg= 0
fort in L:
ifnum < t:
cl+= 1
elifnum == t:
ce+= 1
else:
cg+= 1
return(cl, ce, cg)
# pAB v1.0
defpAB(A, B):
'''计算骰子A对B胜率,和率及负率'''
facenum= len(A)
pF= 0
pE= 0
pW= 0
fora in A:
(cl,ce, cg) = countLtEqGt(a, B)
pF+= cl
pE+= ce
pW+= cg
return(pF, pE, pW)
由于骰子各个面出现的概率相同,所以统计面值大小的个数,就相当于统计概率。有了函数pAB,就可以掌握任意两个骰子之间的战斗情况了。
3
最后,在主函数里,尝试一定的次数,生成3个骰子,使得骰子A胜B,B胜C,C胜A,并打印各个骰子的面值以及胜率。函数如下:
#主函数 v1.0
if__name__ == '__main__':
N= 6 # 骰子面数
T= N*N/2 # 胜数之半
i= 0
n= 0
whilei < 100000:
dieA= GenerateDie(N)
dieB= GenerateDie(N)
dieC= GenerateDie(N)
(pFab,pEab, pWab) = pAB(dieA, dieB)
(pFbc,pEbc, pWbc) = pAB(dieB, dieC)
(pFca,pEca, pWca) = pAB(dieC, dieA)
cond1= (pWab > T) and (pWbc > T) and (pWca > T)
ifcond1:
n+= 1
print'dieA :', dieA
print'dieB :', dieB
print'dieC :', dieC
print'num %d : pWab = %d, pWbc = %d, pWca = %d' % (n, pWab, pWbc, pWca)
print''
i+= 1
print'find %d pairs' % n
在此寻找6面骰子,尝试100000次,先生成3个骰子,然后计算其相互之间的胜率,如果相互胜率都过半,则满足条件,成为非传递骰子,将其打印输出,并统计总共找到多少对骰子。
前面已经确定面值空间为1~6,运行该程序。等待...居然没有找到这样的骰子!即使把尝试次数增加10倍也无法找到。
把面值空间增加2倍,即取
DiceFace= range(1, 13)
再运行,找出了5对:
dieA: [1, 7, 9, 10, 10, 11]
dieB: [6, 6, 7, 7, 7, 12]
dieC: [1, 2, 4, 11, 12, 12]
num1 : pWab = 22, pWbc = 19, pWca = 19
dieA: [2, 3, 4, 5, 6, 12]
dieB: [1, 1, 3, 10, 11, 11]