我从rand(1..117). 假设它打印 80。我想生成另一个比第一个数字少 20 到 20 之间的随机数,但仍然在 1 到 117 之间,即防止负数或大于 117 的数字。
例如,我可以得到 50、35、55、45、64、79、99、88、108 等。每个数字都在 1 到 117 之间,但不能低于或高于前一个数字的 20。
将随机值 20 和最小值 (1) 放入数组中并确定最大值。与值 +20 和 117 类似,但您需要最小值。
这听起来比实际复杂得多:puts r = rand(1..117)
99.times do
puts r = rand([r-20, 1].max..[r+20, 117].min)
end
这是一个解决方案:
def randwalk(min, max, step)
return enum_for(__callee__, min, max, step) unless block_given?
yield n = rand(min..max)
loop do
# min=1 // n=3 // step=20 => subtract up to 2
# min=1 // n=50 // step=20 => subtract up to 20
from = [min - n, -step].max
# max=100 // n=97 // step=30 => add up to 3
# max=100 // n=50 // step=30 => add up to 30
to = [max - n, step].min
yield n += rand(from..to)
end
end
randwalk(1, 117, 20).first(10) # => [90, 89, 103, 87, 106, 94, 96, 99, 97, 103]
randwalk返回一个 Ruby枚举器,它从定义的随机游走中产生与您选择的一样多的值。如果您允许它,它将永远持续下去,并且它不会“跨步”超出给定的最小值/最大值。如果您对实现或如何使用它有任何疑问,请告诉我。
您可以使用clamp来确保数字在给定范围内:
105.clamp(1, 117) #=> 105
120.clamp(1, 117) #=> 117
-15.clamp(1, 117) #=> 1
要生成一个随机序列,其中每个数字都在前一个数字的 ±20 范围内(并且仍在 1..117 范围内),我会使用Enumerator:
random_sequence = Enumerator.new do |y|
min = 1
max = 117
num = rand(min..max)
loop do
y << num
num = rand((num - 20).clamp(min, max)..(num + 20).clamp(min, max))
end
end
random_sequence.take(10)
#=> [12, 31, 50, 47, 57, 73, 66, 46, 60, 46]