Ruby
 Computer >> コンピューター >  >> プログラミング >> Ruby

加重乱数を生成する方法

乱数は通常、「一様分布」と呼ばれるものに従います。つまり、いずれかの番号が選択される可能性が同じです。

ただし、一部の数値を他の数値よりも頻繁に選択する場合は、別の戦略が必要になります。加重乱数ジェネレーター

いくつかの実用的なアプリケーションは次のとおりです。

  • ビデオゲームの戦利品テーブル。敵はさまざまなドロップ率でさまざまなアイテムをドロップできます。
  • より多くのチケットを持っている人が勝つチャンスが多いラッフル。

シンプルな戦略

ラッフルの例を考えると、明らかな解決策を思いつくことができます。「チケット」ごとにアイテムのコピーが1つある配列を生成します。

たとえば、ジョンがラッフルのチケットを4枚購入し、デイビッドが1枚しか購入しない場合、ジョンはデイビッドの4倍のチャンスがあります。

これが実用的な実装です

users  = { john: 4, david: 1 }
raffle = []

users.map do |name, tickets|
  tickets.times { raffle << name }
end

p raffle
# [:john, :john, :john, :john, :david]

p raffle.sample
# :john

購入したチケットごとにその人の名前を1回追加し、そのリストからランダムな名前を選択します。リストに何度も掲載されることで、その名前が選ばれる可能性が高くなります。

このアプローチは非常にシンプルで、リストを作成したらすぐに勝者を選ぶことができるので、私はこのアプローチが好きです。

重みの合計

これを行うためのメモリ効率の高い別の方法がありますが、トレードオフとして、ランダムな値の選択が遅くなります。

アイデアは、1とすべての重みの合計の間の乱数を選択し、この数値以下の重みが見つかるまでループすることです。

ここにコードがあります

def random_weighted(weighted)
  max    = sum_of_weights(weighted)
  target = rand(1..max)

  weighted.each do |item, weight|
    return item if target <= weight
    target -= weight
  end
end

def sum_of_weights(weighted)
  weighted.inject(0) { |sum, (item, weight)| sum + weight }
end

このコードは、キーがアイテムで値が重みであるハッシュを取り込みます。このメソッドは次のように呼び出すことができます:

random_weighted(cats: 5, dogs: 1)
# :cats

何度も実行した後の結果の分布を調べることで、これが期待どおりに機能するかどうかをテストできます。

ここに例があります

counts = Hash.new(0)

def pick_number
  random_weighted(cats: 2, dogs: 1)
end

1000.times { counts[pick_number] += 1 }
p counts

これを数回実行し、出力を見て、比率が適切であるかどうかを確認します。

結論

より洗練されたアルゴリズムがありますが、これら2つはうまく機能するはずです。この記事がお役に立てば幸いです。今後も書き続けられるように、お友達と共有してください。


  1. C#を使用してランダムに文字列を生成するにはどうすればよいですか?

    まず、文字列を設定します。 StringBuilder str = new StringBuilder(); ランダムを使用します。 Random random = new Random((int)DateTime.Now.Ticks); 次に、必要なランダムな文字列の長さの数値をループします。 for (int i = 0; i < 4; i++) {    c = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));    str.Append

  2. Pythonはどのように乱数を生成しますか?

    Pythonの標準配布には、乱数生成機能を備えたランダムモジュールがあります。基本的なrandom()関数は、0から1までのランダムな浮動小数点数を返します >>> import random >>> random.random() 0.5204702770265925 同じモジュールから、連続する範囲の間の乱数を返すrandrange()関数があります。 >>> random.randrange(0,10) 4 リストまたはタプルからアイテムをランダムに選択するchoice()関数もあります >>> random.ch