333

Bridge  Hands : Getting all cards

Math 331: Fall 2024: sjm1@williams.edu

dealstillseeall[numcards_,numdo_] := Module[{},
For[d = 1, d <= 80* numcards * Log[8*numcards] , d++,numdeals[d] = 0];
(* numdeals records how many deals of length d were there before a given person saw everything.
estimating that do not need to go further than numcards * Log[4*numcards] * 4 *)
deck = {};
For[d = 1, d <= 4*numcards, d++, deck = AppendTo[deck,d]]; (* creates deck *)
For[n = 1, n <= numdo, n++,
{
For[d = 1, d <= 4*numcards, d++, seen[d] = 0]; (* initialize to have nothing *)
currnumdeals = 0; (* start with no deals *)
haveall = 0; (* check - do not have all *)
While[haveall  == 0,
{
hand = RandomSample[deck, numcards]; (* creates random hand *)
currnumdeals = currnumdeals + 1; (* dealt another hand *)
For[c = 1, c <= numcards, c++, seen[hand[[c]]] = 1];
If[Sum[seen[i], {i,1,4*numcards}] == 4*numcards, haveall = 1];
If[currnumdeals == 1000 * 4 * numcards, 
{
haveall = 1; Print["Exiting - waiting too long."]
}]; (* end of exit if statement *)
}]; (* end of while loop on haveall = 0 *)
numdeals[currnumdeals] = numdeals[currnumdeals] +1;
}]; (* end of n loop *)


max = 1;
For[d = 1, d <= 8*numcards * Log[8*numcards] , d++,If[numdeals[d] > 0, max = d]]; (* finds max observed *)
For[d = 1, d <= max, d++,numdeals[d] = numdeals[d] * 100.0 / numdo]; (* finds percentage *)
numdealslist = {}; (* list to store values *)
For[d = 1, d <= max, d++, numdealslist = AppendTo[numdealslist, {d, numdeals[d]}]]; (* creates list *)
Print[ListPlot[numdealslist]];
Print[numdealslist];
mean = Sum[ numdeals[d] * d /100.0, {d,1,max}];
stdev = Sqrt[Sum[ numdeals[d] * (d-mean)^2 /100.0, {d,1,max}]];
Print["Mean = ", mean, " and StDev = ", stdev, "."] ;
]

Timing[dealstillseeall[13,100000]]

Timing[dealstillseeall[13,1000000]]

Timing[dealstillseeall[1000,1000]]

Timing[dealstillseeall[1000,10000]]

Timing[dealstillseeall[10000,10]]

Timing[dealstillseeall[10000,100]]

n

52.0 HarmonicNumber[52]

For[r = 1, r <= 10, r++,Timing[dealstillseeall[2^r,100000]]]

ifdealstillseeall[numcards_,numdo_] := Module[{},
For[d = 1, d <= 80* numcards * Log[8*numcards] , d++,numdeals[d] = 0];
(* numdeals records how many deals of length d were there before a given person saw everything.
estimating that do not need to go further than numcards * Log[4*numcards] * 4 *)
deck = {};
For[d = 1, d <= 4*numcards, d++, deck = AppendTo[deck,d]]; (* creates deck *)
For[n = 1, n <= numdo, n++,
{
For[d = 1, d <= 4*numcards, d++, seen[d] = 0]; (* initialize to have nothing *)
currnumdeals = 0; (* start with no deals *)
haveall = 0; (* check - do not have all *)
While[haveall  < 4*numcards,
{
hand = RandomSample[deck, numcards]; (* creates random hand *)
currnumdeals = currnumdeals + 1; (* dealt another hand *)
For[c = 1, c <= numcards, c++, 
If[seen[hand[[c]]] == 0,{ seen[hand[[c]]] = 1; haveall = haveall+1;}]
];
If[currnumdeals == 1000 * 4 * numcards, 
{
haveall = 1; Print["Exiting - waiting too long."]
}]; (* end of exit if statement *)
}]; (* end of while loop on haveall = 0 *)
numdeals[currnumdeals] = numdeals[currnumdeals] +1;
}]; (* end of n loop *)


max = 1;
For[d = 1, d <= 8*numcards * Log[8*numcards] , d++,If[numdeals[d] > 0, max = d]]; (* finds max observed *)
For[d = 1, d <= max, d++,numdeals[d] = numdeals[d] * 100.0 / numdo]; (* finds percentage *)
numdealslist = {}; (* list to store values *)
For[d = 1, d <= max, d++, numdealslist = AppendTo[numdealslist, {d, numdeals[d]}]]; (* creates list *)
(*Print[ListPlot[numdealslist]];*)
Print[numdealslist];
mean = Sum[ numdeals[d] * d /100.0, {d,1,max}];
stdev = Sqrt[Sum[ numdeals[d] * (d-mean)^2 /100.0, {d,1,max}]];
Print["Mean = ", mean, " and StDev = ", stdev, "."] ;
]

Timing[ifdealstillseeall[13,100000]]

THEORY

Below  is  an approach to solve the problem through recurrences / iteratively finding. Some notation first:
s = number of suits
c = number of cards
p = number of players (often p = s)
h = number of cards in a hand (often h = c)
d = number of cards in the deck: d = h p = s c
The number of ways to choose a hand (order doesn’t matter) is (d choose h)
Let x_m be the wait when missing m cards (so have d-m cards seen)
The number of ways to choose a hand and get k of the m missing cards (so have d-m already) is
	 (m choose k) (d - m choose h - k)
Note that (m choose -i) = 0 for any positive i, as is (m choose m+i)

recurrencetofindwaittime[suits_, cards_, players_, hands_] := Module[{},
s = suits; c = cards; p = players; h = hands; d = s * c;
(* x[m] is average weight time when missing m; we find recursively, start knowing x[0] = 0 and x[1] = 1/p, both from the formula and there are p hands! *) 
(* it is convenient to set y[i] = x[i] for i < m if trying to find x[m] and y[m] = 0 *)
(* want y[m] = 0 from bringing things over to solve for x[m] *) 
For[i = 0, i <= d+1, i++, 
{ 
x[i] = 0; y[i] = 0; (* initialize quantities to zero *) 
}];
x[1] = p; y[1] = x[1]; 
numhands = Binomial[d,h]; (* number of ways to choose h cards from deck of d *) 
For[m=2, m <= d, m++,
{
x[m] = Sum[ Binomial[m,k] Binomial[d-m, h-k] (y[m-k] + 1) / numhands, {k,0, Min[h,m]}] / (1 - (Binomial[d-m,h]/numhands));
(* this is the recursive formula, do only for k at most min(h,m) *) 
y[m] = x[m]; (* update y[m] from 0 to x[m] *) 
Print["Wait time x[",m, "] = ",1.0 x[m], " = ", x[m], "." ];
}]; (* end of n loop *)
Print["x[", m-1, "] = ", x[m-1]];
]

recurrencetofindwaittime[4,13,4,13]

Timing[dealstillseeall[13,10000000]]