2012-01-06 23 views

回答

2

爲了簡單起見,我們假設一個數組arr = [x, y, z],我們將從中抽樣值。我們希望看到以下的xyz相對頻率:

frequencies = [5, 2, 1] 

預處理這些頻率來計算利潤率爲我們後續的骰子:

thresholds = frequencies.clone 
1.upto(frequencies.count - 1).each { |i| thresholds[i] += thresholds[i - 1] } 

讓我們總結起來。

max = frequencies.reduce :+ 

現在選擇一個隨機數

roll = 1 + rand max 
index = thresholds.find_index { |x| roll <= x } 

返回arr[index]結果。總結:

def sample arr, frequencies 
    # assert arr.count == frequencies.count 
    thresholds = frequencies.clone 
    1.upto(frequencies.count - 1).each { |i| thresholds[i] += thresholds[i - 1] } 
    max = frequencies.reduce :+ 
    roll = 1 + rand(max) 
    index = thresholds.find_index { |x| roll <= x } 
    arr[index] 
end 

讓我們看看它是如何工作的。

data = 80_000.times.map { sample [:x, :y, :z], [5, 2, 1] } 

一種data直方圖顯示sample作品正如我們所預期的。

Histogram for 80_000.times.map { sample [:x, :y, :z], [5, 2, 1] }

1

一個簡單的方法來實現這與對數概率選擇是模擬硬幣翻轉。生成一個隨機整數0和1,該數組的索引是您獲得的連續1的數量。使用這種方法,選擇2的機會是1的可能性爲1,3的可能性爲1/4,等等。您可以通過生成0到5之間的隨機數來稍微改變概率,並計算連續輪次數大於1,這使得數組中的每個數字可能會像之前那樣顯示。

解決此問題的更好和更一般的方法是使用別名方法。請參閱此問題的答案以獲取更多信息: Data structure for loaded dice?

2
def coin_toss(arr) 
    arr.detect{ rand(2) == 0 } || arr.last 
end 

a = (1..10).to_a 
10.times{ print coin_toss(a), ' ' } #=> 1 1 1 9 1 5 4 1 1 3 

這需要陣列,flips a coin的第一個元素,則返回元件並停止,如果是coinflip「尾料」;否則與下一個元素相同。如果它始終是「頭」,則返回最後一個元素。