電子書籍の厳選無料作品が豊富!

PHP Version 5.1.6を使っています。
例えば
$arr = array(
'key1' => array('name' => 'あ', 'weight' => 1),
'key2' => array('name' => 'い', 'weight' => 1),
'key3' => array('name' => 'う', 'weight' => 3),
);
という連想配列があった時に、
weightの値によってランダムに選ばれる時の差をつけたいのですが、
具体的には、1が最も選ばれ易くて値が大きくなるにつれて選ばれ難くなるようにしたいです。
上の場合だと、key1とkey2が選ばれ易くてkey3は選ばれ難くなります。
逆(1が最も選ばれ難くて、値が大きくなるに連れて選ばれ易い)の場合は
なんとかプログラムで表すことができたのですが、
この場合はどのような感じになるのでしょうか?

A 回答 (3件)

そんなときこそ颯爽とソースを晒してcoolに逃げるに限ります。



[改定前]
$arr = array(
"k1"=>array("value"=>"a","seed"=>1)
,"k2"=>array("value"=>"b","seed"=>2)
,"k3"=>array("value"=>"c","seed"=>3)
);
$arr_child = array();
$keys = array();
foreach($arr as $key => $values)
{
$arr_child[] = $values["seed"];
$keys[] = $key;
}
$sum=0;
foreach($arr_child as $kk => $vv)
$sum = $sum + $vv;
$r = mt_rand(0,$sum);

$ii = 0;
$seed = 0;
$p = 0;
while($r > $seed) {
$p = $ii;
$seed = $seed + $arr_child[$ii];
$ii++;
}

echo $arr[$keys[$p]]["value"];



[改定後]
$arr = array(
"k1"=>array("value"=>"a","seed"=>1)
,"k2"=>array("value"=>"b","seed"=>2)
,"k3"=>array("value"=>"c","seed"=>3)
);
$arr_child = array();
$keys = array();
foreach($arr as $key => $values)
{
$arr_child_tmp[] = $values["seed"];
$keys[] = $key;
}
$sum_tmp=0;
foreach($arr_child_tmp as $kk => $vv)
$sum_tmp = $sum_tmp + $vv;
foreach($arr_child_tmp as $num => $seed_tmp)
{
if($seed_tmp != 0)
$arr_child[] = $sum_tmp / $seed_tmp;
else
$arr_child[] = 0;
}
$sum = 0;
foreach($arr_child as $kk => $vv)
$sum = $sum + $vv;
$r = mt_rand(0,$sum);

$ii = 0;
$seed = 0;
$p = 0;
while($r > $seed) {
$p = $ii;
$seed = $seed + $arr_child[$ii];
$ii++;
}

echo $arr[$keys[$p]]["value"];


つまるところ、逆数の比にしてランダムすれば良いです。
// 仕事しろ俺
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
試してみましたができました。ありがとうございます。

お礼日時:2008/01/09 22:46

選ばれやすいというのは1は3の3倍選ばれやすいということでしょうか?


逆ができたなら1/weightみたいなことで調整できるのでは?

その逆というソースを例示してみてはどうでしょうか?
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
yambejpさんにもANo.1のお礼のサンプルを参考にして(全く違うやり方でも)
考えてもらえないでしょうか?

お礼日時:2008/01/09 22:29

>なんとかプログラムで表すことができたのですが、



そのソースを示した方が回答しやすいと思います。
    • good
    • 0
この回答へのお礼

ご返答ありがとうございます。
すいません、汚いプログラムだったので自分的にはあまり表示したくなかったのですが、
これが逆(1が最も選ばれ難くて、値が大きくなるほど選ばれ易い)のプログラムです。

function random_choice($arr, $weight_key)
{
$cnt = 0;
$wk = array();
foreach ($arr as $key => $val){
if($cnt >= 1){
$wk['start'][$cnt] = $wk['end'][$cnt-1] + 1;
}else{
$wk['start'][$cnt] = 1;
}
$wk['end'][$cnt] = $wk['start'][$cnt] - 1 + $val[$weight_key];
$wk['key'][$cnt] = $key;
$cnt++;
}
//print_r($wk);
$max = count($arr);
$rr = rand($wk['start'][0], $wk['end'][$max-1]);
for ($j = 0; $j < $max; $j++){
if($wk['start'][$j] <= $rr && $rr <= $wk['end'][$j]){
$key = $wk['key'][$j];
break;
}
}
return $key;
}
$arr = array(
'key1' => array('name' => 'あ', 'weight' => 1),
'key2' => array('name' => 'い', 'weight' => 1),
'key3' => array('name' => 'う', 'weight' => 3),
);
$key = random_choice($arr, 'weight');
print "$key<br>\n";

これを(おそらく別のやり方かもしれませんが)どう改造すれば
1が最も選ばれ易くて、値が大きくなるほど選ばれ難くすることができるのでしょうか?

お礼日時:2008/01/09 22:25

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!