main = print $ distribution 10 2
-- i = number of labs left in deck
-- j = number of cards left to draw to make up hand
g 0 _ = delta 0 -- when i gets to zero there are no labs left
g i 0 = delta i -- when j gets to zero we've drawn enough cards so stop and record that we had i labs left in deck
g i j = zipWith (+) (g i (j-1)) (g (i-1) (j+1)) -- either draw a non-lab, or draw a lab
-- number of ways to arrange remaining cards for each possible number of remaining labs
weights nonLabs labs = [choose (nonLabs - 5 - labs + 2 * labsLeft) labsLeft | labsLeft <- [0,1..labs]]
-- distribution of hand sizes
distribution nonLabs labs = reverse $ zipWith (*) (weights nonLabs labs) (g labs 5)
-- infinite list of zeroes except for 1 at ith position
delta i = replicate i 0 ++ [1] ++ repeat 0
-- binomial coefficient n choose k
choose n k = rows !! n !! k
rows = iterate f (1 : repeat 0) where
f r = zipWith (+) r (0:r)