我正在开发一个创建混杂字母组的程序,为此,我正在创建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)
我想将输出字符串转换为数组,但据我所知,输出字符串中会出现一个整数,因此array方法将不适用于它。
如何防止输出的末尾包含整数?
答案 0 :(得分: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
接受参数。
答案 1 :(得分: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
。因此,:Y
(概率为1)将不再被随机抽取,这与它具有正权重的事实相矛盾。
如果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
的范围内不断变化。
这种技术,即所谓的“逆变换方法”,通常用于在仿真模型中生成离散的随机变量。