Playing the lottery

PHP programming forum. Ask questions or help people concerning PHP code. Don't understand a function? Need help implementing a class? Don't understand a class? Here is where to ask. Remember to do your homework!

Moderator: General Moderators

User avatar
aerodromoi
Forum Contributor
Posts: 230
Joined: Sun May 07, 2006 5:21 am

Post by aerodromoi »

volka wrote:
Going even further, I'd say that you need roughly 42 million tickets to win the lottery (at least once) with a probability of >= 95%.
hm, in this case I'd rather play only once with 13.983.816 tickets - each with another combination boosting my chance to "win" to 100% ;)
You're right with this one: If you enter the lottery for a single draw with ~ 14 million combinations, you'll certainly win something.
On the other hand, if you enter the lottery with one ticket per week, you'll need ~42 million tickets and extremely good health.
bokehman wrote:But that is not what I want. I want to return an actual date based on the possiblities. And obviously the date wouldn't be fixed because that's not how the lottery works. It would be different every time but based on the possibilities. And if there were 100 combinations and you played 100 time that doesn't mean your numbers would come up.
That's exactly the difference between volka's proposition and my statement. By saying that you'll need 42 million tickets to win the lottery with a chance of >= 95%, I naturally implied that you only have one ticket per drawing. The same is true for any game (with independent events). Take dices: You'll need at least 17 tries to guarantee that the six comes up at least once with a probability of >= 95%.

However, the lottery could also be won by using ~14 million combinations for a single drawing. Financially, this wouldn't really be a win / win situation, but I have to admit that in terms of life expectancy, volka's idea is much more realistic ;)

Since you mentioned that the candidates in your script get lucky after only ~500,000 weeks/drawings:
In theory (and provided I got the numbers right) your script should only show 3 (out of 100) winners who needed less than 500 000 weeks / drawings to achieve their aim. That's why I calculated this probability (0.0345) in the first place ;)
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

The following code gives a more realistic result but rather than relying on brute force (random numbers) I would like something returns a valid, realistic and fairly unique number of weeks based on the real posibilities and does so in a couple of milliseconds. Has anyone got a realistic idea how to write this? Here's my abridged random code:

Code: Select all

<?php

ini_set('max_execution_time', 100);

$i = 1;
$num = mt_rand(1, 13983816);
while($num !== mt_rand(1, 13983816))
{
	$i++;
}
$ts = (($i % 52.1785)*7*24*60*60) + time();
echo 'You won on ' . date('F jS ', $ts) . floor(date('Y', $ts) + ($i / 52.1785));

?>
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Finally, keeping the old lecture notes was worth something ;)
But keep in mind that stochastics really isn't my strong suit. I mean it!

Each event is independent from previous events. The probability for success is 1/~14 millions for each event. => You have a bernoulli experiment.
The outcome is either a success (all 6 numbers match) or a failure (anything else).
aerodromoi wrote:As far as I know, the total number of ways of selecting k objects from a set of n is calculated with the binomial coefficient.
for "only" one success there is a simpler solution, http://en.wikipedia.org/wiki/Geometric_distribution
In probability theory and statistics, the geometric distribution is either of two discrete probability distributions:

* the probability distribution of the number X of Bernoulli trials needed to get one success, supported on the set { 1, 2, 3, ...}
mt_rand() returns equidistributed random numbers ( !=geometric distributed). There is a method called "inversion method" (literal interpretation of the german term) that is used to "map" equidistributed random numbers to other distributions.
For a geometric distribution this seems to be quite simple. Found another hint in the german version of wikipedia, http://de.wikipedia.org/wiki/Geometrisc ... allszahlen
Simply sum up the P(k+1)=(1-p)P(k) parts until they are as big as the equidistributed random number, k then is the number of experiments needed until one success. You can add some sort of lookup table, I did so for every 500000 iterations.

Code: Select all

<?php
require 'lookup.php';

function foo() {
	// $edrn =  "0.77744368313692681637";
	$edrn = bcdiv(mt_rand(), mt_getrandmax());
	
	list($k, $sum, $pnext) = lookup($edrn);
	echo "equidistributed random number: ", $edrn, "\n";
	echo "		starting with P($k)=$sum\n";
	
	if ( 60000000 <= $k ) {
		echo "P(very large number X) >= $edrn\n";
		return;
	}
	
	while(-1==bccomp($sum, $edrn)) {
		$k++;
		$pnext = bcmul(P_FAILURE, $pnext, 20);
		$sum = bcadd($sum, $pnext, 20);
		if ( 0==$k%100000) {
			echo "		P($k) = $sum \n";
		}
	}
	echo "	P($k) = $sum \n";
}


for($i=0; $i<100; $i++) {
	foo();
}
?>

Code: Select all

<?php // lookup.php
bcscale(20);
define('P_SUCCESS', bcdiv('1', '13983816'));
define('P_FAILURE', bcsub('1', P_SUCCESS));

function lookup($edrn) {
	static $table = null;
	if ( is_null($table) ) {
		$table = array (
			       1=>array('sum'=>P_SUCCESS, 'pk'=>P_SUCCESS),
			  500000=>array('sum'=>'0.03512393876862243580', 'pk'=>'0.00000006899948449546'),
			 1000000=>array('sum'=>'0.06901418521322137956', 'pk'=>'0.00000006657594832894'),
			 1500000=>array('sum'=>'0.10171407146810353961', 'pk'=>'0.00000006423753629926'),
			 2000000=>array('sum'=>'0.13326540767226044970', 'pk'=>'0.00000006198125851218'),
			 2500000=>array('sum'=>'0.16370853542815826387', 'pk'=>'0.00000005980423008944'),
			 3000000=>array('sum'=>'0.19308237938231023634', 'pk'=>'0.00000005770366748143'),
			 3500000=>array('sum'=>'0.22142449699404678221', 'pk'=>'0.00000005567688490637'),
			 4000000=>array('sum'=>'0.24877112655667206198', 'pk'=>'0.00000005372129091965'),
			 4500000=>array('sum'=>'0.27515723353221726022', 'pk'=>'0.00000005183438509809'),
			 5000000=>array('sum'=>'0.30061655525759571894', 'pk'=>'0.00000005001375484074'),
			 5500000=>array('sum'=>'0.32518164408155083578', 'pk'=>'0.00000004825707229108'),
			 6000000=>array('sum'=>'0.34888390898666310491', 'pk'=>'0.00000004656209135336'),
			 6500000=>array('sum'=>'0.37175365574820102843', 'pk'=>'0.00000004492664482336'),
			 7000000=>array('sum'=>'0.39382012568276248743', 'pk'=>'0.00000004334864161795'),
			 7500000=>array('sum'=>'0.41511153303697252426', 'pk'=>'0.00000004182606410143'),
			 8000000=>array('sum'=>'0.43565510106194453854', 'pk'=>'0.00000004035696550525'),
			 8500000=>array('sum'=>'0.45547709682077739402', 'pk'=>'0.00000003893946743890'),
			 9000000=>array('sum'=>'0.47460286477406139483', 'pk'=>'0.00000003757175748912'),
			 9500000=>array('sum'=>'0.49305685918522055289', 'pk'=>'0.00000003625208690083'),
			10000000=>array('sum'=>'0.51086267538746650274', 'pk'=>'0.00000003497876834240'),
			10500000=>array('sum'=>'0.52804307995296433376', 'pk'=>'0.00000003375017374779'),
			11000000=>array('sum'=>'0.54462003980201618702', 'pk'=>'0.00000003256473223501'),
			11500000=>array('sum'=>'0.56061475029022638239', 'pk'=>'0.00000003142092809782'),
			12000000=>array('sum'=>'0.57604766230882331612', 'pk'=>'0.00000003031729886812'),
			12500000=>array('sum'=>'0.59093850843326389821', 'pk'=>'0.00000002925243344483'),
			13000000=>array('sum'=>'0.60530632815327036766', 'pk'=>'0.00000002822497028986'),
			13500000=>array('sum'=>'0.61916949221630606104', 'pk'=>'0.00000002723359568811'),
			14000000=>array('sum'=>'0.63254572611706958440', 'pk'=>'0.00000002627704206803'),
			14500000=>array('sum'=>'0.64545213276116433221', 'pk'=>'0.00000002535408637948'),
			15000000=>array('sum'=>'0.65790521433284379071', 'pk'=>'0.00000002446354853068'),
			15500000=>array('sum'=>'0.66992089339429137240', 'pk'=>'0.00000002360428987902'),
			16000000=>array('sum'=>'0.68151453324479041029', 'pk'=>'0.00000002277521177620'),
			16500000=>array('sum'=>'0.69270095756389329367', 'pk'=>'0.00000002197525416212'),
			17000000=>array('sum'=>'0.70349446936536574881', 'pk'=>'0.00000002120339421121'),
			17500000=>array('sum'=>'0.71390886928457311100', 'pk'=>'0.00000002045864502207'),
			18000000=>array('sum'=>'0.72395747322427270731', 'pk'=>'0.00000001974005435852'),
			18500000=>array('sum'=>'0.73365312938039464186', 'pk'=>'0.00000001904670343007'),
			19000000=>array('sum'=>'0.74300823466941139372', 'pk'=>'0.00000001837770571733'),
			19500000=>array('sum'=>'0.75203475057944473292', 'pk'=>'0.00000001773220583999'),
			20000000=>array('sum'=>'0.76074421846387707546', 'pk'=>'0.00000001710937846079'),
			20500000=>array('sum'=>'0.76914777429828777855', 'pk'=>'0.00000001650842723290'),
			21000000=>array('sum'=>'0.77725616291895978094', 'pk'=>'0.00000001592858377959'),
			21500000=>array('sum'=>'0.78507975176125368577', 'pk'=>'0.00000001536910671267'),
			22000000=>array('sum'=>'0.79262854411541328048', 'pk'=>'0.00000001482928068410'),
			22500000=>array('sum'=>'0.79991219191666020905', 'pk'=>'0.00000001430841547267'),
			23000000=>array('sum'=>'0.80694000808605732544', 'pk'=>'0.00000001380584509883'),
			23500000=>array('sum'=>'0.81372097843836250775', 'pk'=>'0.00000001332092697666'),
			24000000=>array('sum'=>'0.82026377317113770005', 'pk'=>'0.00000001285304108937'),
			24500000=>array('sum'=>'0.82657675795047254041', 'pk'=>'0.00000001240158919730'),
			25000000=>array('sum'=>'0.83266800460705727716', 'pk'=>'0.00000001196599407396'),
			25500000=>array('sum'=>'0.83854530145737093960', 'pk'=>'0.00000001154569876764'),
			26000000=>array('sum'=>'0.84421616326142920883', 'pk'=>'0.00000001114016588814'),
			26500000=>array('sum'=>'0.84968784083135808771', 'pk'=>'0.00000001074887692105'),
			27000000=>array('sum'=>'0.85496733030207252568', 'pk'=>'0.00000001037133156389'),
			27500000=>array('sum'=>'0.86006138207670499440', 'pk'=>'0.00000001000704708675'),
			28000000=>array('sum'=>'0.86497650945755832907', 'pk'=>'0.00000000965555771522'),
			28500000=>array('sum'=>'0.86971899697420944619', 'pk'=>'0.00000000931641403539'),
			29000000=>array('sum'=>'0.87429490841889450081', 'pk'=>'0.00000000898918241776'),
			29500000=>array('sum'=>'0.87871009459937798880', 'pk'=>'0.00000000867344446334'),
			30000000=>array('sum'=>'0.88297020082007584563', 'pk'=>'0.00000000836879646975'),
			30500000=>array('sum'=>'0.88708067410008819564', 'pk'=>'0.00000000807484891383'),
			31000000=>array('sum'=>'0.89104677013788062823', 'pk'=>'0.00000000779122595417'),
			31500000=>array('sum'=>'0.89487356003091065304', 'pk'=>'0.00000000751756495006'),
			32000000=>array('sum'=>'0.89856593675980462876', 'pk'=>'0.00000000725351599888'),
			32500000=>array('sum'=>'0.90212862144436627432', 'pk'=>'0.00000000699874148666'),
			33000000=>array('sum'=>'0.90556616938011238460', 'pk'=>'0.00000000675291565894'),
			33500000=>array('sum'=>'0.90888297586259945149', 'pk'=>'0.00000000651572420306'),
			34000000=>array('sum'=>'0.91208328180733371227', 'pk'=>'0.00000000628686384512'),
			34500000=>array('sum'=>'0.91517117917208974376', 'pk'=>'0.00000000606604196448'),
			35000000=>array('sum'=>'0.91815061618904856289', 'pk'=>'0.00000000585297621869'),
			35500000=>array('sum'=>'0.92102540241297532475', 'pk'=>'0.00000000564739418105'),
			36000000=>array('sum'=>'0.92379921359196366382', 'pk'=>'0.00000000544903299444'),
			36500000=>array('sum'=>'0.92647559636733785027', 'pk'=>'0.00000000525763903368'),
			37000000=>array('sum'=>'0.92905797280834647722', 'pk'=>'0.00000000507296758329'),
			37500000=>array('sum'=>'0.93154964478783277571', 'pk'=>'0.00000000489478252145'),
			38000000=>array('sum'=>'0.93395379820382178337', 'pk'=>'0.00000000472285602100'),
			38500000=>array('sum'=>'0.93627350705303946654', 'pk'=>'0.00000000455696825670'),
			39000000=>array('sum'=>'0.93851173736126867198', 'pk'=>'0.00000000439690712366'),
			39500000=>array('sum'=>'0.94067135097588199244', 'pk'=>'0.00000000424246796882'),
			40000000=>array('sum'=>'0.94275510922494412114', 'pk'=>'0.00000000409345332515'),
			40500000=>array('sum'=>'0.94476567644767825982', 'pk'=>'0.00000000394967266304'),
			41000000=>array('sum'=>'0.94670562340122792477', 'pk'=>'0.00000000381094214400'),
			41500000=>array('sum'=>'0.94857743054761538559', 'pk'=>'0.00000000367708438714'),
			42000000=>array('sum'=>'0.95038349122530476620', 'pk'=>'0.00000000354792824217'),
			42500000=>array('sum'=>'0.95212611470927939195', 'pk'=>'0.00000000342330856992'),
			43000000=>array('sum'=>'0.95380752916372735228', 'pk'=>'0.00000000330306603141'),
			43500000=>array('sum'=>'0.95542988449094128356', 'pk'=>'0.00000000318704688387'),
			44000000=>array('sum'=>'0.95699525507997798002', 'pk'=>'0.00000000307510278699'),
			44500000=>array('sum'=>'0.95850564245941356489', 'pk'=>'0.00000000296709060664'),
			45000000=>array('sum'=>'0.95996297785622104470', 'pk'=>'0.00000000286287224080'),
			45500000=>array('sum'=>'0.96136912466498127827', 'pk'=>'0.00000000276231443400'),
			46000000=>array('sum'=>'0.96272588083056280794', 'pk'=>'0.00000000266528861323'),
			46500000=>array('sum'=>'0.96403498114697665500', 'pk'=>'0.00000000257167072219'),
			47000000=>array('sum'=>'0.96529809947537366099', 'pk'=>'0.00000000248134105986'),
			47500000=>array('sum'=>'0.96651685088423846537', 'pk'=>'0.00000000239418413056'),
			48000000=>array('sum'=>'0.96769279371462229022', 'pk'=>'0.00000000231008849696'),
			48500000=>array('sum'=>'0.96882743157242945387', 'pk'=>'0.00000000222894663308'),
			49000000=>array('sum'=>'0.96992221525100656976', 'pk'=>'0.00000000215065479076'),
			49500000=>array('sum'=>'0.97097854458609962336', 'pk'=>'0.00000000207511286649'),
			50000000=>array('sum'=>'0.97199777024573634776', 'pk'=>'0.00000000200222427162'),
			50500000=>array('sum'=>'0.97298119545717938195', 'pk'=>'0.00000000193189581205'),
			51000000=>array('sum'=>'0.97393007767319286216', 'pk'=>'0.00000000186403756400'),
			51500000=>array('sum'=>'0.97484563017981678001', 'pk'=>'0.00000000179856276654'),
			52000000=>array('sum'=>'0.97572902364780809137', 'pk'=>'0.00000000173538770035'),
			52500000=>array('sum'=>'0.97658138762931034904', 'pk'=>'0.00000000167443159229'),
			53000000=>array('sum'=>'0.97740381200209718315', 'pk'=>'0.00000000161561650390'),
			53500000=>array('sum'=>'0.97819734836317291382', 'pk'=>'0.00000000155886723173'),
			54000000=>array('sum'=>'0.97896301137325405506', 'pk'=>'0.00000000150411121682'),
			54500000=>array('sum'=>'0.97970178005427595025', 'pk'=>'0.00000000145127845059'),
			55000000=>array('sum'=>'0.98041459904101415646', 'pk'=>'0.00000000140030137846'),
			55500000=>array('sum'=>'0.98110237978895966648', 'pk'=>'0.00000000135111482057'),
			56000000=>array('sum'=>'0.98176600173970030028', 'pk'=>'0.00000000130365589128'),
			56500000=>array('sum'=>'0.98240631344536666347', 'pk'=>'0.00000000125786390418'),
			57000000=>array('sum'=>'0.98302413365362166786', 'pk'=>'0.00000000121368031305'),
			57500000=>array('sum'=>'0.98362025235442462900', 'pk'=>'0.00000000117104862400'),
			58000000=>array('sum'=>'0.98419543179022621615', 'pk'=>'0.00000000112991432673'),
			58500000=>array('sum'=>'0.98475040743050392678', 'pk'=>'0.00000000109022482937'),
			59000000=>array('sum'=>'0.98528588891216095647', 'pk'=>'0.00000000105192938317'),
			59500000=>array('sum'=>'0.98580256094684237667', 'pk'=>'0.00000000101497902287'),
			60000000=>array('sum'=>'0.98630108419638204964', 'pk'=>'0.00000000097932650559')
		);
	}
	
	$k_prev = 1;
	foreach($table as $k=>$c) {
		if (1==bccomp($c['sum'], $edrn) )
			break;
		$k_prev = $k;
	}
	
	return array($k_prev, $table[$k_prev]['sum'], $table[$k_prev]['pk']);
	
}
?>
The only test for plausibility I applied is:
aerodromoi wrote:Giong even further, I'd say that you need roughly 42 million tickets to win the lottery (at least once) with a probability of >= 95%.
41500000=>array('sum'=>'0.94857743054761538559', 'pk'=>'0.00000000367708438714'),
42000000=>array('sum'=>'0.95038349122530476620', 'pk'=>'0.00000000354792824217'),
;)
User avatar
Oren
DevNet Resident
Posts: 1640
Joined: Fri Apr 07, 2006 5:13 am
Location: Israel

Post by Oren »

aerodromoi wrote:This would imply that you can choose one number more than once (up to six times, actually).
The last time I looked, there was only one cross per number ;)
Oren wrote:You can choose any number from 1 to 49 if I'm right.
Well, I wasn't right. I had that feeling... that's why I added the "if I'm right" - I wasn't sure and it's been a long time since the last time I played the lottery :P
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

volka wrote:Finally, keeping the old lecture notes was worth something
Sorry to be thick but I don't understand how to use that code. When I tried it it just timed out.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

Hm, you're running this via webserver?
then try

Code: Select all

<?php
require 'lookup.php';

function foo() {
	$edrn = bcdiv(mt_rand(), mt_getrandmax());
	list($k, $sum, $pnext) = lookup($edrn);
	if ( 60000000 <= $k ) {
		return array(-1,-1);
		return;
	}
       
	while(-1==bccomp($sum, $edrn)) {
		$k++;
		$pnext = bcmul(P_FAILURE, $pnext, 20);
		$sum = bcadd($sum, $pnext, 20);
	}

	return array($k, $edrn);
}




echo "<pre>\n";
for($i=0; $i<100; $i++) {
	set_time_limit(10);
	$r = foo();
	printf("%10s weeks (p=%6s)\n", number_format($r[0], 0), round($r[1], 4));
	flush();
}
echo "</pre>\n";
?>
User avatar
aerodromoi
Forum Contributor
Posts: 230
Joined: Sun May 07, 2006 5:21 am

Post by aerodromoi »

The basic idea behind volka's script is to check how many times (in this case: weeks) a player would
have to enter the lottery in order to win the jackpot with a certain probability.
In this case, he used the geometric distribution, whereas I went for a n-ray bernoulli experiment and later opted for a simpler inequality.
The result is roughly the same.

@bokehman
I've modified your script somewhat. According to this version, the arithmetical average for winning the lottery for
1000 people is ~ 7 million weeks.

However, this result only points to a >= 40% probability... (where's the flaw? ;) )
Image

Code: Select all

<?php

function getnumbers($times)
{   
    $outputarr = array();
    
    for($i=0;$i<$times;$i++) 
    {
      $outputarr[$i] = mt_rand(1, 13983816);
    }
    
    return $outputarr;
}

function getaverage($inputarray)
{
  $total;
  
  for ($i=0;$i<count($inputarray);$i++)
  {
    $total += $inputarray[$i];
  }
  
  return round($total / count($inputarray));
}

function gettime($time)
{
  $years   = floor($time / 365);
  $weeks   = round(($time - $years * 365) / 52,2);
  
  $out_str = $years." years and ".$weeks." weeks";
  
  return $out_str;
}

$draw_arr = getnumbers(1000);
$average  = getaverage($draw_arr);

print ("The average player should win after ".gettime($average)." (".number_format($average)." drawings).<br />\n"); 
?>
Last edited by aerodromoi on Sat Oct 14, 2006 5:32 pm, edited 1 time in total.
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

aerodromoi wrote:However, this result only points to a >= 40% probability... (where's the flaw? ;) )
getaverage() makes no sense in this context.
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

aerodromoi wrote:I've modified your script somewhat. According to this version, the arithmetical average for winning the lottery for
1000 people is ~ 7 million weeks.

However, this result only points to a >= 40% probability... (where's the flaw? ;) )
I'd say the average should be about 9.6 million. This thread has given me a few good ideas. I like the lookup table. I want to convert these calculations into a random result but that is based on the odds but doesn't use a loop. Back in a while.
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

volka wrote:Hm, you're running this via webserver?
Is there a way I can feed this code the probability and it will return the week. For example I feed it 0.5 (or 50%) and it returns 9.6 million weeks? Or I feed it the weeks and it returns the probability of having won? Damn I suck!
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

bokehman wrote:For example I feed it 0.5 (or 50%)
Yes, just pass $edrn to foo().

Code: Select all

<?php
require 'lookup.php';

function foo($edrn) {
	list($k, $sum, $pnext) = lookup($edrn);
	
	if ( -1==$k ) {
		return array(-1,-1);
	}
	       
	while(-1==bccomp($sum, $edrn)) {
		$k++;
		$pnext = bcmul(P_FAILURE, $pnext, 20);
		$sum = bcadd($sum, $pnext, 20);
	}
	return array($k, $edrn);
}


print_r(foo('0.5'));
?>
Array
(
[0] => 9692848
[1] => 0.5
)
bokehman wrote:Or I feed it the weeks and it returns the probability of having won?
You can change lookup() and let it return the last entry < #events. The index of $table is #events.
User avatar
aerodromoi
Forum Contributor
Posts: 230
Joined: Sun May 07, 2006 5:21 am

Post by aerodromoi »

volka wrote:
aerodromoi wrote:However, this result only points to a >= 40% probability... (where's the flaw? ;) )
getaverage() makes no sense in this context.
After a few hours of sleep, I'd say that the catch is that my script does not take
into account that the individual events have to be independent.

Right now, the script only prints out the average number of tickets a player would
have to fill in each week in order to win the lottery. Naturally, this number should
converge against 13,983,816 / 2 which boils down to ~ 7 Million tickets.

If the events were independent (as they should), a player would definitely need
at least 9,692,875 weeks for a probability >= 50%.
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

volka wrote:Finally, keeping the old lecture notes was worth something ;)
What is this code supposed to do? I'm baffled!
User avatar
volka
DevNet Evangelist
Posts: 8391
Joined: Tue May 07, 2002 9:48 am
Location: Berlin, ger

Post by volka »

:?:
bokehman wrote:
volka wrote:Hm, you're running this via webserver?
Is there a way I can feed this code the probability and it will return the week. For example I feed it 0.5 (or 50%) and it returns 9.6 million weeks? Or I feed it the weeks and it returns the probability of having won? Damn I suck!
volka wrote:
bokehman wrote:For example I feed it 0.5 (or 50%)
Yes, just pass $edrn to foo().

Code: Select all

<?php
require 'lookup.php';

function foo($edrn) {
	list($k, $sum, $pnext) = lookup($edrn);
	
	if ( -1==$k ) {
		return array(-1,-1);
	}
	       
	while(-1==bccomp($sum, $edrn)) {
		$k++;
		$pnext = bcmul(P_FAILURE, $pnext, 20);
		$sum = bcadd($sum, $pnext, 20);
	}
	return array($k, $edrn);
}


print_r(foo('0.5'));
?>
Array
(
[0] => 9692848
[1] => 0.5
)
bokehman wrote:Or I feed it the weeks and it returns the probability of having won?
You can change lookup() and let it return the last entry < #events. The index of $table is #events.
User avatar
bokehman
Forum Regular
Posts: 509
Joined: Wed May 11, 2005 2:33 am
Location: Alicante (Spain)

Post by bokehman »

volka wrote:Is there a way I can feed this code the probability and it will return the week. For example I feed it 0.5 (or 50%) and it returns 9.6 million weeks
Sorry, but I just can't unravel the code or why it is so complex and slow. This code really made me believe this was complicated but in the end with a little bit of help and a lot of explaining from many kind people including everyone in this thread I came up with the following which runs in less than a millisecond:

Code: Select all

echo '<p>Number of plays before reaching 50% probability: '.
      number_format(NumPlays(Probability(49, 6), 50));

echo '<p>Random number of plays before winning the jackpot for the first time: '.
      number_format(NumPlaysRandom(Probability(49, 6)));

function Probability($d, $n)
{
    if($d<$n||$n<1) return 0;
    $r = 1;
    while($n&&$r*=$d--/$n--);
    return 1/$r;
}

function NumPlays($prob, $percent)
{
    if($prob == 1) return 1;
    return intval(log(1-($percent/100))/log(1-$prob)+1);
}

function NumPlaysRandom($prob)
{
    if($prob == 1) return 1;
    $r = mt_rand(1, mt_getrandmax())/mt_getrandmax();
    return intval(log($r)/log(1-$prob)+1);
}
Post Reply