给定像[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
这样的数组,我希望得到一个考虑位置的随机值。
我希望1
弹出的可能性大于10
。
这样的事情可能吗?
答案 0 :(得分:2)
为了简单起见,我们假设一个数组arr = [x, y, z]
,我们将从中采样值。我们希望看到以下x
,y
和z
的相对频率:
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
正如我们预期的那样工作。
答案 1 :(得分: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为'tails'时停止;否则与下一个元素相同。如果它一直是“头”,则返回最后一个元素。
答案 2 :(得分:1)
使用选择的对数概率来实现此功能的一种简单方法是模拟硬币翻转。生成随机整数0和1,要选择的数组的索引是您获得的连续1的数量。使用这种方法,选择2的可能性是1/2的可能性是1,3可能是1/4等。您可以通过生成0到5之间的随机数来略微改变概率,并计算连续轮数高于1,这使得数组中的每个数字4/5可能与之前的数字一样。
解决此问题的更好,更通用的方法是使用别名方法。有关更多信息,请参阅此问题的答案: Data structure for loaded dice?