# 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