import os, math from decimal import Decimal # functions and code to calculate binomial coeffecients and probabilities of winning ping pong games # used to calculate the liklihood of me beating Dan Hostetler in ping pong # arnie larson # www.arnie.frisbolero.com # calculate the liklihood of winning a ping pong game.. winning n out of m points with a probability p. def liklihood(n,m,p): if not (n<=m): print('n must be greater than m') else: q = Decimal(str(1-p)) a = choose(n,m)*Decimal(str(math.pow(p,n)))*Decimal(str(math.pow(q,m-n))) #print(' probability of winning %s out of m points %s with p = %s is %s'%(n,m,p,a)) return a # calculate m choose n. (m is bigger) def choose(n,m): num = Decimal(str(math.factorial(m))) den = Decimal(str(math.factorial(n))) * Decimal(str(math.factorial(m-n))) try: choose = num/den except: print('Overflow error in %s / %s calculation'%(num,den)) return num/den # probability of winning a ping pong game given the probability of winning a given point p def gameProb(p): prob = 0 for points in range(21,41): prob += liklihood(21,points,p) return prob # probability of winning at ping pong, winning n games out of m, given the probability of winning a given point p def gameProbFromEven(p,n,m): prob = 0 for points in range(n,m): # n = 16, then it's a game to 5. so 5, 2*5 - 2 prob += liklihood(n,m,p) return prob # probability of winning a game with two distinct point probabilities. After player gets to n, winning percentage goes down to p2 from p1 # the assumption here is that after a critical point in the game, the second player will play much better. def gameProb2(p1,p2,n): if n > 20 or p2>p1: print('choose n around 15 and p2 less than p1') else: prob = 0 for firstgames in range(n,n+21): temp = liklihood(n,firstgames,p1)*liklihood(21-n,41-firstgames,p2) #print('checking for n = %s, subprobability is: %5f'%(firstgames,temp)) prob += temp return prob # quits when the probability of having one a game after n games > .5 def winOnceMedian(g): # todo: Loop through starting with n = 1; begin = 1 start = 2 prob = 0 while(True): for games in range(begin,start+1): prob+=liklihood(games,start,g) print('after %s games, the liklihood of winning is: %5f when p: %5f'%(start,prob,g)) if prob>Decimal('.5'): print('mean number of games: %s where liklihood of winning is greater than one half' % start) break begin = start start = math.floor(start*1.7) # probability of winning a game out of 'num' games for probability of winning a given game is p def winOnceMedian(p,num): prob = 0 for games in range(1,num+1): prob+=liklihood(games,num,p) #print('probability of winning a game is %8f after %4d games with a p_game of %5f' % (prob, num, p)) return prob # Calculates the probability of winning a game out of 'num' games, approximates this by only calculating the first 'n' dominant terms # This approximation is valid if the p is very low, (less than a few percent or so) def winOnceMedian2(p,num,n): prob = 0 for games in range(1,n): t = liklihood(games,num,p) prob+=t #print('probability of winning (%s) games out of %s with a p_game of %5f' % (t, num, p)) return prob p = [] p.append(gameProb(.33)) p.append(gameProb(.25)) print('probability of winning match if p = .33 : %5f'%p[0]) print('probability of winning match if p = .25 : %5f'%p[1]) # this is the closes I can really get to calculating the true liklihood of winning a given game.. p.append(gameProb2(.33,.20,16)) print('probability of winning match if p at start = .33 and p at end = .20 is: %5f'%p[2]) #winOnceMedian(.5,2) for pgame in p: num = 11 while(True): prob = winOnceMedian2(pgame,num,8) #print('probability of winning a game is %8f after %4d games with a p_game of %5f' % (prob, num, pgame)) if prob > Decimal('.5'): print('probability of winning a game is %8f after %4d games with a p_game of %5f' % (prob, num, pgame)) break num+=4 #prob1 = winOnceMedian2(p2,2100,8) #print('probability of winning a game is %8f after %4d games with a p_game of %5f' % (prob1, 2100, p1)) #prob2 = winOnceMedian2(p2,2300,8) #print('probability of winning a game is %8f after %4d games with a p_game of %5f' % (prob2, 2300, p2)) #winOnceMedian(p2)