[Search for users] [Overall Top Noters] [List of all Conferences] [Download this site]

Conference rusure::math

Title:Mathematics at DEC
Moderator:RUSURE::EDP
Created:Mon Feb 03 1986
Last Modified:Fri Jun 06 1997
Last Successful Update:Fri Jun 06 1997
Number of topics:2083
Total number of notes:14613

1884.0. "Probability: Lucky draw" by FORTY2::BOYES (My karma ran over my dogma) Thu Jul 28 1994 10:32

This is a real-world problem: I collect cards from  trading card set: this
set is made up of twenty distinct cards. All of these cards have the same
probability of being 'drawn' from the pool of several million cards. I draw
twenty cards from the pool of cards, hoping all of them will be distinct.
I draw seventeen different cards and three others. How lucky was I? i.e. what is
the probability that on drawing twnety cards I would have *at least* seventeen
distinct?

+Mark+
T.RTitleUserPersonal
Name
DateLines
1884.1CSC32::D_DERAMODan D'Eramo, Customer Support CenterFri Jul 29 1994 00:003
        You were really lucky. :-)
        
        Dan
1884.2RUSURE::EDPAlways mount a scratch monkey.Wed Aug 03 1994 17:55156
    My program says the chance of getting 17 or more different cards is
    about .00305282, or about one in 328.  (This program ignores the size
    of the pool, which we can do since it is so large.)
    
    
    				-- edp
    
    
#include	<stdio.h>
#include	<stdlib.h>


typedef int	Boolean;
#define	TRUE	1
#define	FALSE	0


#define	MEMORY	0
#define	USAGE	1
void	panic(int error)
{
	switch (error)
	{
		case MEMORY:
			fprintf(stderr, "Out of memory.\n");
			break;
		case USAGE:
			fprintf(stderr, "Usage:  count num [limit]\n");
			break;
	}
	exit(1);
}


typedef struct partition
{
	int	t;	/* number of last used element */
	int	e[1];	/* elements */
}	Partition;


Boolean	next_partition(Partition **p, int n)
{
	int	i, limit, sum;

	/* If we are passed a null pointer, create and initialization a
	   partition. */
	if (!*p)
	{
		*p = (Partition *)malloc((n-1)*sizeof(int) + sizeof **p);
		if (!*p)
			panic(MEMORY);
		/* Set up one element containing all the members. */
		(*p)->t = 0;
		(*p)->e[0] = n;
		return TRUE;
	}

	/* Otherwise, increment the partition we are given to the next
	   partition. */
	for (i = (*p)->t; i >= 0 && (*p)->e[i] == 1; i--)
		;
	/* If we reached the last partition, free the structure. */
	if (i < 0)
	{
		free((*p));
		return FALSE;
	}
	limit = --(*p)->e[i];
	sum = (*p)->t-i + 1;
	for (i++; sum; i++)
	{
		(*p)->e[i] = sum < limit ? sum : limit;
		sum -= (*p)->e[i];
	}
	(*p)->t = i-1;

	return TRUE;
}


/* Figure out how many ways this partition pattern can be ordered. */
double	num_orders(Partition *p, int n)
{
	int	i, j;
	double	num;

	num = 1;
	for (i = 1; i <= n; i++)
		num *= i;
	for (i = 0; i <= p->t; i++)
		for (j = 1; j <= p->e[i]; j++)
			num /= j;

	return num;
}


/* Figure out how many ways this partition can be filled with objects. */
double	num_fills(Partition *p, int n)
{
	double	num;
	int	i, length;

	/* Select any type to use for the first bin. */
	num = n--;
	length = 1;

	for (i = 1; i <= p->t; i++)
	{
		/* The elements in this bin can be chosen from any one
		   of the types not yet used. */
		num *= n--;

		/* Is this bin the same size as the previous one? */
		if (p->e[i] == p->e[i-1])
			/* If so, the bins can be reordered. */
			num /= ++length;
		else
			/* Otherwise, start counting again. */
			length = 1;
	}

	return num;
}


int	main(int argc, char *argv[], char *arge[])
{
	int	i, limit, n;
	Partition	*p;
	double	total, subset;

	if (argc != 2 && argc != 3)
		panic(USAGE);

	n = atoi(argv[1]);
	if (n <= 0)
		panic(USAGE);
	limit = argc >= 3 ? atoi(argv[2]) : 0;

	for (total = 1, i = 0; i < n; i++)
		total *= n;
	for (p = NULL, subset = 0; next_partition(&p, n);)
	{
#if 0
		for (i = 0; i <= p->t; i++)
			printf("%d ", p->e[i]);
		printf("\n");
#endif
		if (p->t >= limit-1)
			subset += num_orders(p, n) * num_fills(p, n);
	}
	printf("Subset = %lg.  Total = %lg.  Ratio = %lg.\n", subset, total,
		subset/total);
}
1884.3different program - same answerAUSSIE::GARSONachtentachtig kacheltjesThu Aug 04 1994 05:09151
    re .2

    I use slightly different calculations and get a probability of around 1 in
    327 for a reasonably large pool (say 200000 cards in total). (I would
    therefore have to disagree with .1 as to how 'lucky' the base noter
    was.)

    My program does not handle the partitioning in a flexible manner i.e. I
    hard coded the ways in which the non-unique cards are "grouped". I also
    don't compute the probabilities exactly but just compute using G-float
    to get an approximation.

    The program is attached. No prizes for coding style. It was a quick
    hack.

/* must compile
	$ CC/G_FLOAT x
   and link
	$ LINK x,CG/OPT
   where CG.OPT contains
   SYS$LIBRARY:VAXCRTLG/SHARE
*/

#ifndef D
#define D if(0)
#endif

double C( int n, int r )
{
    double t = 1;
    int i;

    if ( r < 0 )
	return 0;
    else if ( r == 0 )
	return 1;
    else if ( r > n / 2 )
	r = n - r;

    for ( i = 0; i < r; i++ )
	t *= n-i,
	t /= r-i;

    return t;
}

double P( int n, int r )
{
    double t = 1;
    int i;

    for ( i = 0; i < r; i++ )
	t *= n-i;

    return t;
}

double power( int base, int expon )
{
    double t = 1;
    int i;

D   printf("%d ** %d = ",base,expon);

    if ( expon <= 0 )
    {
D	printf("\n");
	return 1;
    }

    for ( i = 0; i < 32; i++ )
    {
	t *= t;
	if ( expon < 0 )
	    t *= base;
	expon <<= 1;
    }

D   printf("%.15E\n",t);

    return t;
}

double nways( int r, int s, int dups )
{
/* number of ways of choosing r from r ranks by s suits where the result is
"dups" duplicates i.e. that many cards not contributing to the set of unique
cards drawn. */

/* P(r,x) or C(r,x) choose the x ranks to be tied up in groups
   C(s,dups') indistinguishable ways of choosing a group of dups'
   C(r-x,r-dupss) choose the remaining ranks (all unique)
   power(s,r-dupss) indistinguishable ways of choosing the unique cards
*/

    switch ( dups )
    {
    case 0:
	return power(s,r);
	break;
    case 1:
	       /* one pair */
	return C(r,1) * C(s,2) * C(r-1,r-2) * power(s,r-2);
	break;
    case 2:
	       /* one triple */
	return C(r,1) * C(s,3) * C(r-1,r-3) * power(s,r-3) +
	       /* two pairs */
	       C(r,2) * C(s,2) * C(s,2) * C(r-2,r-4) * power(s,r-4);
	break;
    case 3:
	       /* one four of a kind */
	return C(r,1) * C(s,4) * C(r-1,r-4) * power(s,r-4) +
	       /* three pairs */
	       C(r,3) * C(s,2) * C(s,2) * C(s,2) * C(r-3,r-6) * power(s,r-6) +
	       /* a triple and a pair */
	       P(r,2) * C(s,3) * C(s,2) * C(r-2,r-5) * power(s,r-5);
	break;
    default:
	return 0;
    }
}

main(int argc, char*argv[])
{
    int r;
    int s;
    int n;
    double d;
    double n0,n1,n2,n3;
    double sigman;

    r = argc > 1? atoi(argv[1]) : 4;
    s = argc > 2? atoi(argv[2]) : 5;
    n = r * s;
    d = C(n,r);
    printf("d = %.15E\n",d);

    n0 = nways( r, s, 0 );
    printf("n0 = %.15E\n",n0);
    n1 = nways( r, s, 1 );
    printf("n1 = %.15E\n",n1);
    n2 = nways( r, s, 2 );
    printf("n2 = %.15E\n",n2);
    n3 = nways( r, s, 3 );
    printf("n3 = %.15E\n",n3);

    sigman = n0+n1+n2+n3;
    printf("sigma n[i] = %.15E\n",sigman);
    printf("prob       = %.15E (1 in %d)\n",sigman/d,(int)(d/sigman));
}
1884.4FORTY2::BOYESMy karma ran over my dogmaThu Aug 04 1994 09:417
Re .2,.3: Thanks for the answer!


+Mark+

(My luck seems to have run out: I'm now on 25 cards and still haven't
got the last three)
1884.5That's a lotta strikeouts (Ks)VMSDEV::HALLYBFish have no concept of fireThu Aug 04 1994 13:004
> (My luck seems to have run out: I'm now on 25 cards and still haven't
> got the last three)
    
    Kirk, Spock & McKoy?
1884.6Magic: The gathering - Uncommon artifactsFORTY2::BOYESMy karma ran over my dogmaThu Aug 04 1994 13:541
Ivory Cup, Living Wall and Ornithopter, for what its worth
1884.7CSC32::D_DERAMODan D'Eramo, Customer Support CenterThu Aug 04 1994 14:536
        re .3,
        
        You don't consider pulling off a 1-in-327 on the very first
        try to be really lucky?
        
        Dan
1884.8someone "had" toAUSSIE::GARSONachtentachtig kacheltjesFri Aug 05 1994 09:187
    re .7
    
    Obviously we are not really in disagreement since there is no
    definition of what "really lucky" is... but given the number of cards
    in the pool I would assume a large number of players. If noone got 17
    or more distinct cards out of his first 20 cards, now that would be
    improbable.
1884.9FORTY2::BOYESMy karma ran over my dogmaFri Aug 05 1994 09:569
There's also the point that the twenty cards I was after are just a subset 
of what I find in the fifteen-card packs I buy: there are five other types
of card with three levels of comparitive rarity each in the Magic set: 
possibly anyone with a few hundred cards could find some sort of pattern if
they looked hard enough (e.g. 'A disproportiante number of my cards were 
drawn by the same artist'). 


+Mark+