1

これをできる限り説明しようと思います。各アイテムに残っているアイテムの量に基づいて、ランダムな値 (色) を生成する必要があります。

5 つの色があり、各色に 10 個のスポットがあるとします。

Red = 10
Blue = 10
Green = 10
Yellow = 10
Black = 10

すべての色に 10 個のスポットがあるため、各色のチャンスが等しい最初のランダムな色を取得したいと思います。次に、選択された最初の値が赤の場合、リストは次のようになります

Red = 9
Blue = 10
Green = 10
Yellow = 10
Black = 10

次に、他の色で利用可能なスポットがより高いため、次のランダム値は赤の重みをわずかに低くします。赤が再び選ばれたとしましょう。リストは次のようになります。

Red = 8
Blue = 10
Green = 10
Yellow = 10
Black = 10

そのため、次のラウンドでは赤の重みがさらに低くなります。

基本的には、各スポットが均等に選ばれる可能性を等しくしたいのですが、スポットを均等に分散させたいと思います (シーケンシャルになることはありません)。

色は 5 より多い場合も少ない場合もあり、利用可能なスポットは最大 1000 まで可能です。データは DB に保存されますが、1 秒あたり複数のスポット リクエストが発生する可能性があるため、このデータを保存する方法に関する提案も歓迎します。スポットが要求されると、カラー グループから削除されます。

大変感謝します!

4

3 に答える 3

0

アイテムを重量として扱い、ランダムな値を選択して重量と比較できます。リストを調べて、リストの確率よりも小さくなるまで、ランダム値から重みを減算します。アイテムが使用される次の反復では、空になるまで確率が変化します。

   x = random([0.0, 1.0])
   for i in 0..n
       if x < probabilities[i]
        choose(i)
         break
       else
         x -= probabilities[i]
     end
    end
于 2013-07-29T23:19:03.717 に答える
0

スポットをデータベースに保存したいので、他のソリューションとは別のアプローチをとったでしょう。

複数のスレッドがそれぞれ利用可能な色を取得できるようにモデル化するには、色をセットまたは外部キーとして示すスポットのテーブルと、一意のキーとデフォルトの NULL を持つリース ID を用意することもできます。

最初に、まだリース ID (uuid) でリースされていないランダムな行を更新することによって、ランダムな要素を選択します。そこから、他のリクエストはそれを選択できなくなり、リースIDによる選択クエリを実行して、その色を見つけることができます。これにより、競合状態が発生せず、行ベースのロックで同時に複数のクライアントにサービスを提供できます。

10,000 個のスポットで色とリース ID を保存するため、80kB 未満になります。テーブル全体が常にキャッシュされます。

于 2013-07-30T00:09:19.007 に答える
-1

このようなことを試すことができます。あなたが言及したような配列があり、DB からデータが取得されているとします。

red   => 100
green => 200
blue  =>  50

組み合わせたすべての色の値を加算します (この場合は 350)。1 からそれまでのランダムな値を選択します。

$randValue = rand(1, 350);

次に、ループを使用して、0 または負になるまで色の値を徐々に減算します。

foreach ($colors as $key => $value) {
    $randValue = $randValue - $value;
    if ($randValue < 1) {
        $pickedColor = $key;
        // and substract 1 from this color in the DB
        break;
    }
}

したがって、この場合、$randValue124 の場合、緑色になります。

于 2013-07-29T23:18:52.500 に答える