3

I am working on a lottery script where from a list of 5 users a random one is choosed. My problem is that some of the users must have 50% more chances to win.

For example

bob - 1 chance
rob - 1.5 chance
mike - 1 chance
john - 1 chance
todd - 1.5 chance

How can i make this work? I was thinking build an array and use array_rand to get a random user but i have no ideea how to distribute the chances.

Thanks

JMax
  • 26,109
  • 12
  • 69
  • 88
keepwalking
  • 2,644
  • 6
  • 28
  • 63
  • 1
    possible duplicate of [Generating random results by weight in PHP?](http://stackoverflow.com/questions/445235/generating-random-results-by-weight-in-php) – Ben Lee Oct 10 '11 at 08:57

6 Answers6

4

Change you list to

bob - 1 chance 
bob - 1 chance 
rob - 1.5 chance 
rob - 1.5 chance 
rob - 1.5 chance 
mike - 1 chance 
mike - 1 chance 
john - 1 chance 
john - 1 chance 
todd - 1.5 chance 
todd - 1.5 chance 

Then when you select one from this list, some have better or worse chance at winning.

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
  • 1
    This is an elegant solution! However, it gets messy very quickly when the chance differences become something like 72.2% . :) – janoliver Oct 10 '11 at 09:01
  • @janoliver - It is down to ratios. You do not have to actually construct the list. For your example suppose we have percentages and use the first decimal place. i.e. 0 - 100.0 (1000 possible values). Have the list tom (0 - 12.5), barry (12.6 - 27.6) etc)) then pick a number between 0 to 1000. Search the list. Which person falls in the range?( – Ed Heal Oct 11 '11 at 20:06
4

For an uneven distribution like this, the approach is as follows:

Add all the weightings together, to get a total. This is the figure that you would use as a random number ceiling. In your example, this would be 6.

Now build an array with each element having the sum of all the elements below it in the array (the sort order doesn't matter).

Thus you would have an array like this:

bob = 1
rob = 2.5
mike = 3.5
john = 4.5
todd = 6

Now you can get the random number, and pick the array element which is the highest one where the score is less than the random number.

This will give you your weighted randomness, regardless of how uneven the weightings are.

Spudley
  • 166,037
  • 39
  • 233
  • 307
0

By Changes you probably mean chances. Well, what you can do is make an array, that has the users:

$boughtLotteryTicket = array('bob', 'rob', 'rob', 'mike', 'john', 'todd', 'todd');

And do whatever you wanted to it :). Since you added them twice, they both have double the possibility to win. Same principle when participating in any lottery. Buy more tickets == higher change of winning.

pyronaur
  • 3,515
  • 6
  • 35
  • 52
0

Sum up all the chances weighted with the changes:

$sum =$pSum = 0;
foreach($users as $participant)
    $sum += $participant['change'];

$rand = rand()/get_randmax();
foreach($users as $participant) {
    $pSum += $participant['change']/$sum;
    if($pSum > $rand) {
        $winner = $participant;
        break;
    }
}
janoliver
  • 7,744
  • 14
  • 60
  • 103
0

This is not likely the best way to handle it but for the sake of getting something this small done I assume for a work related thing..

make a simple array. Of names. Those who have 50% extra of a chance to win I would assume is equal to 2 in 1. So of those names, I would do duplicates in the array.

$lottoNames = array('bob', 'rob', 'rob', 'mike', 'john', 'todd', 'todd');
$x = count($lottoNames)-1;
$lotto = rand(0, $x);
echo $lottoNames[$lotto];

I can't say this would work but its a shawdy idea to run with again for simplicity of it all.

chris
  • 36,115
  • 52
  • 143
  • 252
0

This might work:

$chance = array(
    'bob' => 1,
    'rob' => 1.5,
    'mike' => 1,
    'john' => 1,
    'todd' => 1.5,
);

$range = array_sum($chance);
$offset = rand(0, $range-1);

$i = 0;
foreach ($chance as $person => $weight)
{
    $i += $weight;
    if ($i <= $offset)
    {
        echo $person . ' won';
        break;
    }
}
Tom
  • 3,031
  • 1
  • 25
  • 33