[英]How do I generate a sum of random numbers?
如果我的取值范围是0-70,则我要选择五个随机数,并且随机数的总和应大于140,然后小于220,然后这样做,直到五个随机数之和在范围140..220,然后显示这五个随机数。 *
这是我到目前为止所做的:
5.times {r=rand (0..70); puts "#{r}"}
要么:
5.times {puts "#{[*0...70].sample}"}
如果您需要实际的数字而不是总和,请使用此衬纸:
nums = [*0..70].sample(5) until (140..220) === (nums || []).inject(:+)
如果数字可以重复,请改用此方法:
nums = 5.times.collect {rand(0..70)} until (140..220) === (nums || []).inject(:+)
第二个版本的多行版本,没有统计错误(帽子提示samuil):
digits = []
valid = 140..220
until valid === digits.inject(:+)
digits = []
5.times { digits << rand(0..70) }
end
答案不是很简短,但是看起来很清晰,并且是红宝石风格的。
e = Enumerator.new do |y|
loop do
y << 5.times.map { rand(0..70) }
end
end
e.find { |ary| (140..220).include? ary.inject(&:+) }
首先,我们定义枚举器,该枚举器返回从0..70范围内随机分配的一批数字。 稍后,使用#find
方法,我们将寻找第一个条目,该条目将满足(140..220)范围内的求和条件。
用纯红宝石
sum = [*0..70].sample(5).inject(&:+) until (140..220) === sum
如果使用ActiveSupport,则可以使用#sum
代替inject(&:+)
。
只是为了好玩,这是我能想到的最具说明性的代码:
repeat { (0..70).sample(5) }.detect { |xs| xs.reduce(:+).in?(140...220) }
不存在的抽象的实现留给读者练习:-)
boundary = 140..220
numbers = *0..70
begin
numbers.sample( 5 ).reduce( :+ ).tap do |sum|
fail unless boundary === sum
end
rescue
retry
end
经讨论后,我想在一个扔catch
和throw
例子, 这是我最近主张自己 ,但是这在某种程度上似乎并没有成为合适的机会。 因此,让我提出另一种无例外的做法:
class Object
def ergo; yield self end
end
numbers.ergo do |ary|
rslt = ary.sample( 5 ).reduce( :+ )
boundary === rslt ? rslt : redo
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.