加权信发电机

问题描述 投票:0回答:2

我的工作,创建了信混乱的群体,对于这个程序,我创建2台加权信发电机,一个辅音字母,一个元音。

目前,我有使用哈希值进行加权的加权数生成器,我可以来电来函采摘功能与我想它返回的字母数(如pick_vowel(3))

def pick_vowel(x)
  vowels = { A: 15, E: 21, I: 13, O: 13, U: 5 }
  v_choice = []
  vowels.map {|letter, number| number.times {v_choice << letter}}
  x.times {print v_choice.shuffle!.pop}
end

我们的想法是,然后向得到的字符串传递给一个功能赋予一定的长度的所有可能的组合,使用以下代码:

def solver(vowel)
  puts (2..9).flat_map{|size| board.combination(size).map(&:join)}
end

但是当我传递字符串我得到下面的错误信息(在这种情况下,x = 6):

in `block in solver': undefined method `combination' for 6:Integer (NoMethodError)

我想输出字符串转换为数组,但据我所知没有出现在输出字符串一个整数,所以该阵列方法并不适用于它。

如何防止在最后包含一个整数我的输出?

arrays ruby function random hash
2个回答
0
投票

假设

vowels = { A: 5, E: 8, I: 4, O: 7, U: 3, Y: 1 }

我理解这个散列值绘制相关联的密钥的权重。你首先构造(以不同的方式):

v_choice = vowels.flat_map { |k,v| [k]*v }
  #=> [:A, :A, :A, :A, :A,
  #    :E, :E, :E, :E, :E, :E, :E, :E,
  #    :I, :I, :I, :I,
  #    :O, :O, :O, :O, :O, :O, :O,
  #    :U, :U, :U,
  #    :Y] 

接下来,您执行

x.times {print v_choice.shuffle!.pop}    

假设第一洗牌产生以下:

v_choice
  #=> [:O, :O, :E, :U, :U, :O, :A, :E, :E, :E, :U, :I, :A, :I,
  #    :E, :A, :O, :O, :E, :E, :O, :A, :I, :A, :O, :E, :I, :Y] 

接着

print v_choice.pop

打印"Y",并删除:Y唯一v_choice。因此,(与概率1):Y将随机抽取没有更多的,矛盾的是它具有正权重的事实。

如果vowels的值不重量,但在数字元音的有限集合一个可以大大简化。计算v_choice后,只需要编写

puts v_choice.sample(x).join
  # EOOYEIIEOI

要么

puts v_choice.shuffle[0,x].join
  # EOOUOEEIAE

现在让我们假设vowels的价值确实是权重。然后,我们只需要编写

x = 10
x.times { print v_choice.sample }
# OAEYEUAOAO

如果vowels的值大,v_choice也相应较大。这将影响到内存的要求,但不执行速度。如果对内存的需求非常昂贵(不太可能,也许),一个可以做到以下几点。

tot_wts = vowels.values.sum.to_f
  #=> 28.0
cum = 0
cum_dist = vowels.map do |v,wt|
  cum_wt = cum + wt/tot_wts
  cum = cum_wt
  [v, cum_wt]
end
  #=> [[:A, 0.17857142857142858],
  #    [:E, 0.4642857142857143],
  #    [:I, 0.6071428571428572],
  #    [:O, 0.8571428571428572],
  #    [:U, 0.9642857142857143],
  #    [:Y, 1.0]]

在舍入误差的情况下,我们可能会设置

cum_dist[-1][-1] = 1.0

然后,我们可以生产正是如此加权样本。

x = 10
x.times do
  rn = rand
  print cum_dist.find { |_,cum| rn < cum }.first
end
# EAAOOEEIOA

注意,我们不能写

print cum_dist.find { |_,cum| rand < cum }.first

因为rand返回的值将不断find的块内发生变化。

该技术中,所谓的“逆变换方法”,通常用于产生仿真模型离散随机变元。


0
投票

问题就在这里:

x.times {print v_choice.shuffle!.pop}

上述打印的值x倍,并返回x的值。这是Integer#times是如何工作的。

相反,你需要:

x.times.map { v_choice.shuffle!.pop }

或更好,

v_choice.shuffle!.pop(x)

因为Array#pop接受的说法。

© www.soinside.com 2019 - 2024. All rights reserved.