birthday.py

publicité
#
#
#
#
#
Birthday Problem
Filename: birthday.py
Author: David Radcliffe
Created: 2013 July 15
License: CC BY 3.0
# Helper functions
def binom(n,k,p=1): # Binomial coefficient n choose k (multiplied by
p**k)
k = min(k, n-k)
ans = 1
for j in xrange(k):
ans = (p*ans*(n-j))/(j+1)
return ans
def multinom(n, v, p=1): # Multinomial coefficient
ans = 1
for k in v:
ans *= binom(n, k, p)
n -= k
return ans
# Q(n, 1, d) = probability that no two people out of a group of n
# will have matching birthdays, given that there are d days in a year.
#
# More generally,
# Q(n, k, d) = probability that a birthday is shared by some k people out
#
of n, but no birthday is shared by more than k people.
#
# A recursive formula for Q(n, k, d) is given at
# http://mathworld.wolfram.com/BirthdayProblem.html
# (and implemented here).
#
# Note that the time required to compute this formula
# grows exponentially in k.
#
# P(n, k, d) = probability that k or more people _do_ share the same
birthday
#
= 1 - sum(Q(n,i,d), i=1 to k-1)
#
Memo = { }
def Q(n, k, d):
if (n, k, d) in Memo:
return Memo[(n, k, d)]
if n >= d*k:
return 0
p = 1.0 / d
if k == 1:
ans = 1.0
for i in range(n):
ans *= p * (d-i)
else:
ans = 0.0
for i in xrange(1, int(n/k)+1):
s = 0.0
for j in xrange(1, k):
s += Q(n-i*k, j, d-i) * (1 - p*i)**(n-i*k)
ans += s * binom(d, i) * multinom(n, (k,)*i, p)
Memo[(n, k, d)] = ans
return ans
def P(n, k, d):
ans = 1.0
for i in xrange(1, k):
ans -= Q(n, i, d)
return ans
if __name__ == '__main__':
print P(40, 2, 365)
print P(500, 6, 365) # Probability that in a group of 500 people
# at least five have a common birthday
Téléchargement