Reputation: 1371
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
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
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