1

如果我有一个从 0 到 70 的数字范围,我想选择五个随机数,并且随机数的总和高于 140 并低于 220。我想这样做直到五个随机数的总和在范围 140..220,然后显示这五个随机数。*

这是我到目前为止所做的:

5.times {r=rand (0..70); puts "#{r}"}

或者:

5.times {puts "#{[*0...70].sample}"}
4

5 回答 5

3

如果您需要实际数字,而不是总和,请使用这一行:

nums = [*0..70].sample(5) until (140..220) === (nums || []).inject(:+)

如果数字可以重复,请改用:

nums = 5.times.collect {rand(0..70)} until (140..220) === (nums || []).inject(:+)

第二个的多行版本,没有统计错误(hat tip samuil):

digits = []
valid = 140..220
until valid === digits.inject(:+)
  digits = []
  5.times { digits << rand(0..70) }
end
于 2013-06-22T11:49:34.290 回答
2

不是很简短的答案,但似乎很清楚,而且是红宝石风格的。

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) 范围内的总和条件。

于 2013-06-22T12:01:19.623 回答
1

在纯红宝石中

sum = [*0..70].sample(5).inject(&:+) until (140..220) === sum

如果您使用 ActiveSupport,那么您可以使用#sum而不是inject(&:+).

于 2013-06-22T11:24:56.077 回答
1

只是为了好玩,这是我能想到的最具声明性的代码:

repeat { (0..70).sample(5) }.detect { |xs| xs.reduce(:+).in?(140...220) }

不存在的抽象的实现留给读者练习:-)

于 2013-06-22T12:05:44.977 回答
-1
boundary = 140..220
numbers = *0..70
begin
  numbers.sample( 5 ).reduce( :+ ).tap do |sum|
    fail unless boundary === sum
  end
rescue
  retry
end

在讨论之后,我想举一个我最近提倡catchthrow例子,但这似乎不是一个合适的机会。所以让我用另一种方式来做这件事,没有例外:

class Object
  def ergo; yield self end
end

numbers.ergo do |ary|
  rslt = ary.sample( 5 ).reduce( :+ )
  boundary === rslt ? rslt : redo
end
于 2013-06-22T11:32:08.263 回答