重み付きのランダム抽選関数を作る(PHP)

過去に書いた記事の焼きまわしです。

tyablog.net のドメインに変更して、wpXクラウドに引っ越ししたので、
古い記事はこちらに移していきたい。


重み付きの抽選ロジックは既に色々なところで紹介されていますが、
ちょっと必要になったので作ってみました。

重み付抽選関数

配列要素の値に重み(確率)となる整数値を入れて渡すと抽選された要素のキーを返します。

サンプルでは、hash配列を渡していますが、array配列でも同様に要素のキーを返します。

/*
* 配列から1つの要素キーを抽選する。
*
* $entries: array($key => $weight, ...)
*           配列の値に抽選の割合(重み)を整数値で指定。
*/
function array_rand_weighted($entries){
    $sum  = array_sum($entries);
    $rand = rand(1, $sum);

    foreach($entries as $key => $weight){
        if (($sum -= $weight) < $rand) return $key;
    }
}

entryies という、ハッシュ配列を引数に渡すと、
ハッシュ配列の値(重み)によって、抽選してくれます。

返り値は、抽選結果となるキーを返します。

使ってみる 


// 抽選候補となる配列 // キーが要素で、値が重みになる。 $entries = array( "1等" => 10, "2等" => 20, "3等" => 30, "ハズレ" => 40, ); // 抽選(こんな感じで使用する) $result_key = array_rand_weighted($entries);

ほんとにランダム?

本当に確率通りに抽選されているか、100回と、1000回動作させてみた結果です。
使うentriesは、上で使ったものを利用してみます。

// ▼100回実行 抽選結果をカウント
$result = array();
for($i=0; $i<100; $i++){
    $key = array_rand_weighted($entries);
    @$result[$key]++;
}
print_r($result);
/*
 Array (
    [ハズレ] => 40
    [3等]   => 32
    [2等]   => 21
    [1等]   => 7
 )
*/

// ▼1000回実行 抽選結果をカウント
$result = array();
for($i=0; $i<1000; $i++){
    $key = array_rand_weighted($entries);
    @$result[$key]++;
}
print_r($result);
/*
 Array (
    [ハズレ] => 418
    [3等]   => 291
    [2等]   => 203
    [1等]   => 88
 )
*/

ちゃんと確率通りに分布しているようです。

おしまい

過去に書いた記事ですが、結構需要があったので転記しました。
みんなPHPを使う頻度が多いんですかね〜。

コメントを残す