inemanja
inemanja

Reputation: 1371

Creating not-so-random list from given array in PHP

I need to generate list of n ($size_of_list) names... Possible members are given in array ($names_list) which gives name and chances of appearance of that name. So it is an array of 40 arrays of string and integer:

$names_list = array (
                     0 => array ('name' => "Mike", 'frequency' => 8),
                     1 => array ('name' => "Jane", 'frequency' => 7),
                     2 => array ('name' => "Leopold", 'frequency' => 1),
                     3 => array ('name' => "George", 'frequency' => 5),
...
                     39 => array ('name' => "Mark", 'frequency' => 6)
                    )

$names_list[0] = array('name' => "Mike", 'frequency' => 8) means that $name="Mike" has $frequency (or chance) of 8, and "Leopold" has chance value 1 - small chance to appear...

Upvotes: 0

Views: 135

Answers (2)

inemanja
inemanja

Reputation: 1371

My idea is to expand array with new value 'rnd' which represents sum of $frequency and previous elements rnd (where first element 'rnd' is first element's 'frequency')

$names_list[0]['rnd'] = $names_list[0]['frequency'];
for ($i=1; $i<count($names_list); $i++)
    $names_list[$i]['rnd'] = $names_list[$i]['frequency'] + $names_list [$i-1]['rnd'];  

and expanded array would look like this:

$names_list = array (
                     0 => array ('name' => "Mike", 'frequency' => 8, 'rnd' => 8),
                     1 => array ('name' => "Jane", 'frequency' => 7, 'rnd' => 15),
                     2 => array ('name' => "Leopold", 'frequency' => 1, 'rnd' => 16),
                     3 => array ('name' => "George", 'frequency' => 5, 'rnd' => 21),
//... other elements
                     39 => array ('name' => "Mark", 'frequency' => 8, 'rnd' => $sum_of_all_frequencies)
                    )

And then set $rand_max to value of last elements 'rnd', and then to create finale list by comparing $random and all 'rnd' values...

$rand_max = $names_list[count($names_list)-1]['rnd'];

for ($i=1; $i<$size_of_list; $i++)
{
    $random = rand (1, $rand_max);
    $result = $names_list[0]['name'];
    foreach ($names_list as $key => $val)
        if ( ($random) > ($val['rnd']) )
            $result = $names_list[$key+1]['name'];

    $list[$i] = $result;
}

This solution works, but i think there are better (smarter) ways...
I would appreciate any help/suggestion...

Upvotes: 0

mr. Pavlikov
mr. Pavlikov

Reputation: 1012

Specify $size_of_list and check out $result in the end. This uses random depending on weight.

$result = array();

$total = 0;
foreach ($names_list as $row) {
    $total += $row['frequency'];
}

$max = mt_getrandmax();
$pre_sum = $total / $max;

for ($i = 0; $i < $size_of_list; ++$i) {

    $sum = $pre_sum * mt_rand(0, $max); // $sum = $total * (mt_rand(0, $max)/$max);

    foreach ($names_list as $row) {
        if (($sum -= $row['frequency']) < 0) {
            $result[] = $row['name'];
            break;
        }
    }
}

var_dump($result);

Upvotes: 1

Related Questions