我如何从更频繁返回对象的数组中估算?

时间:2012-01-06 23:28:38

标签: ruby arrays

给定像[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]这样的数组,我希望得到一个考虑位置的随机值。

我希望1弹出的可能性大于10

这样的事情可能吗?

3 个答案:

答案 0 :(得分: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 :(得分: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?