PDA

View Full Version : Probability

Digger3000
07-04-2007, 03:02 PM
Let's say I have something like this: \$colors=array("red", "blue"); And I want to randomly echo one of the things in the array. But let's say I want it to be more likely for it to be red than blue. I guess I could put red into the array twice, but is there a quicker way? I'm very, very lazy.

07-04-2007, 03:20 PM
The only easy way, without actually writing out the probability equations using PHP code, is to create an array with the correct number of entries with the "weight" you want -

\$colors=array("red", "blue"); // gives one out of two chance for red
\$colors=array("red", "red", "blue"); // gives two out of three chance for red
\$colors=array("red", "red", "red", "blue"); // gives three out of four chance for redYou could shorten the data structure to a color/weight pair, but you would need to add code to produce the expanded array with all the entries. To get a computer to randomly pick from the weighted possibilities, you need a "pool" of the available choices to pick from.

You can use the shuffle(...) or array_rand(...) function instead of a random number to actually generate a random entry.

Digger3000
07-04-2007, 03:44 PM
I made up a solution that seems like it could work. What do you think?

\$colors=array("2|red", "1|blue");
\$newcolors=array();
foreach(\$colors as \$key => \$value) {
\$split=explode("|", \$value);
\$probability=\$split[0];
\$thecolor=\$split[1];
\$i=1;
while(\$i <= \$probability) {
\$newcolors[]=\$thecolor;
\$i++;
}
}

07-04-2007, 03:57 PM
Try it and see if it produces the array you expect. That's where writting, testing, and debugging code gets fun, getting code to do what you want.

Digger3000
07-04-2007, 04:15 PM
I did print_r(\$newcolors); and got this: "Array ( [0] => Red [1] => Red [2] => Blue )" So it seems to work.

ralph l mayo
07-05-2007, 12:42 AM
Just another method you can use if it suits you... it simulates an array with duplicates determining priority instead of actually making one, but I don't know whether it's faster or not.

function array_weighted_rand(\$ary)
{
# Pick a random index as if the array was arranged so that it actually
# had more entries of the values with higher probabilities
# eg. for values = [ red, blue, green]
# and probabilities = [ 2, 1, 3]
# assume something like:
# 0 => red
# 1 => red
# 2 => blue
# 3 => green
# 4 => green
# 5 => green
\$prob_idx = mt_rand(0, array_sum(array_values(\$ary)) - 1);

# Find where the selected index maps to the real indices by calculating
# a running sum on the probabilities and returning whenever the index
# is exceeded.
\$running_sum = 0;
foreach (\$ary as \$value=>\$prob)
{
\$running_sum += \$prob;
if (\$running_sum > \$prob_idx)
return \$value;
}
}

\$colors = array(
'red' => 2,
'blue' => 1,
'green' => 3
);
\$picks = array(
'red' => 0,
'blue' => 0,
'green' => 0
);

for (\$idx = 0; \$idx < 100000; ++\$idx)
{
++\$picks[array_weighted_rand(\$colors)];
}
print_r(\$picks);