ruby - 选择一个随机选项,其中每个选项被选中的概率不同

标签 ruby algorithm random

假设给您三个“选项”,ABC

您的算法必须随机选择并返回一个。为此,只需将它们放在一个数组 {A,B,C} 中并生成一个随机数(0、1 或 2),这将是元素在返回数组。

现在,这个算法有一个变体:假设 A 有 40% 的机会被选中,B 有 20%,而 C 40%。如果是这种情况,您可以采用类似的方法:生成一个数组 {A,A,B,C,C} 并生成一个随机数 (0, 1, 2, 3, 4)选择要返回的元素。

行得通。但是,我觉得效率很低。想象一下,将此算法用于大量 选项。你会创建一个有点大的数组,可能有 100 个元素,每个元素代表 1%。现在,这仍然不是很大,但假设您的算法每秒使用多次,这可能会很麻烦。


我考虑过创建一个名为 Slot 的类,它有两个属性:.value.size。为每个选项创建一个插槽,其中 .value 属性是选项的值,而 .size 相当于该选项的出现次数在数组中。然后生成一个从0到总出现次数的随机数,看看这个数落在了哪个slot上。

我更关心算法,但这是我的 Ruby 尝试:

class Slot
  attr_accessor :value
  attr_accessor :size
  def initialize(value,size)
    @value = value
    @size  = size
  end
end

def picker(options)
  slots = []
  totalSize = 0
  options.each do |value,size|
    slots << Slot.new(value,size)
    totalSize += size
  end
  pick = rand(totalSize)
  currentStack = 0
  slots.each do |slot|
    if (pick <= currentStack + slot.size)
      return slot.value
    else
      currentStack += slot.size
    end
  end
  return nil
end

50.times do
  print picker({"A" => 40, "B" => 20, "C" => 40})
end

哪些输出:

CCCCACCCCAAACABAAACACACCCAABACABABACBAAACACCBACAAB


是否有更有效的方法来实现选择随机选项的算法,其中每个选项都有不同的被选中概率?

最佳答案

最简单的方法可能是写一个case语句:

def get_random()
  case rand(100) + 1
    when  1..50   then 'A'
    when 50..75   then 'B'
    when 75..100  then 'C'
  end
end

问题是你不能传递任何选项,所以如果你想让它能够接受选项,你可以写一个这样的函数。下面的那个与您写的非常相似,但更短一些:

def picker(options)
  current, max = 0, options.values.inject(:+)
  random_value = rand(max) + 1
  options.each do |key,val|
     current += val
     return key if random_value <= current
  end
end

# A with 25% prob, B with 75%.
50.times do
  print picker({"A" => 1, "B" => 3})
end
# => BBBBBBBBBABBABABBBBBBBBABBBBABBBBBABBBBBBABBBBBBBA

# If you add upp to 100, the number represent percentage.
50.times do
  print picker({"A" => 40, "T" => 30, "C" => 20, "G" => 10})
end
# => GAAAATATTGTACCTCAATCCAGATACCTTAAGACCATTAAATCTTTACT 

关于ruby - 选择一个随机选项,其中每个选项被选中的概率不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19261061/

相关文章:

ruby-on-rails - 如何创建复杂的 Nested -> Belongs To 对象?

algorithm - 我如何计算这两个过程的预计完成时间

python - Python/Django 中的个性化/随机 URL

Java排序: random gen numbers same as sorted numbers(in terms of order)

ruby - 如何创建一个新的 Ruby gem?

ruby - 为什么 bash -l -c "CMD"让 ruby 找到我的 gem ?

arrays - Ruby - 测试每个数组元素,得到一个结果

algorithm - 找到前缀和变化的 O(n) 解

c++ - std::list 的排序成员函数使用哪种排序算法?

php - 如何限制数据库调用的随机数为随机数加五?