我想知道是否有办法生成一个数组,例如,从 0 开始,增加 1 直到达到 3,然后减少 1 直到再次达到 0,例如
[0,1,2,3,2,1,0]
如果我能提前指定数组中的值数量,那就太好了。例如,如果我可以设置数组的下限 (0(、上限 (3(、增量 (1( 和长度 (9(:
[].oscillate(0,3,1,9( 会给我这个:
[0,1,2,3,2,1,0,1,2]
截至目前,我能想到的最好的事情是:
values = []
until values.count >= 9
values.pop
x=0
values << x && x+=1 while x < 3
values << x && x-=1 while x >= 0
end
有趣的练习!
你正在寻找一个三角波。维基百科上的公式是标准形状(介于-1和1之间(,但这里有一个适用于任何波的位置,周期和振幅的改编版本:
def triangle_wave(min, max, increment, length, offset = 0)
amplitude = max - min
period = 2 * amplitude
Array.new(length) do |i|
min + ((increment * (i + offset) - amplitude) % period - amplitude).abs
end
end
puts triangle_wave(0, 3, 1, 9) == [0, 1, 2, 3, 2, 1, 0, 1, 2]
# true
p triangle_wave(-3, 3, 1, 20)
# => [-3, -2, -1, 0, 1, 2, 3, 2, 1, 0, -1, -2, -3, -2, -1, 0, 1, 2, 3, 2]
p triangle_wave(5, 9, 2, 9)
# => [5, 7, 9, 7, 5, 7, 9, 7, 5]
p triangle_wave(0, 1, 0.25, 9)
# => [0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0]
p triangle_wave(-3, 0, 1, 9, 3)
# => [0, -1, -2, -3, -2, -1, 0, -1, -2]
p triangle_wave(0, 1, 1, 9)
# => [0, 1, 0, 1, 0, 1, 0, 1, 0]
min
应该小于max
,increment
应该是正的,max-min
应该能被increment
整除。这些是对输入的限制,而不是对输出的限制:任何波都可以产生。
这个问题可能是使用 Ruby 触发器运算符的教科书示例。
由于这个问题只有在存在非负整数steps
时才有意义,因此high = low + steps * increment
,我将该方法的参数high
替换为steps
。
def oscillate(low, steps, increment, length)
high = low + steps * increment
n = low
length.times.each_with_object([]) do |_,a|
a << n
n += (n==low)..(n==high-increment) ? increment : -increment
end
end
oscillate(0,3,1,9)
#=> [0, 1, 2, 3, 2, 1, 0, 1, 2]
oscillate(-1, 4, 2, 16)
#=> [-1, 1, 3, 5, 7, 5, 3, 1, -1, 1, 3, 5, 7, 5, 3, 1]
为了展示这里发生的事情,我将稍微修改代码并添加一些puts
语句,然后使用第一个示例运行它。
def oscillate(low, steps, increment, length)
high = low + steps * increment
puts "high = #{high}"
n = low
length.times.each_with_object([]) do |_,a|
a << n
diff = (n==low)..(n==high-increment) ? increment : -increment
print "n=#{n}, a<<n=#{a}, diff=#{diff}, "
n += diff
puts "n+=diff=#{n}"
end
end
oscillate(0,3,1,9)
high = 3
n=0, a<<n=[0], diff= 1, n+=diff=1
n=1, a<<n=[0, 1], diff= 1, n+=diff=2
n=2, a<<n=[0, 1, 2], diff= 1, n+=diff=3
n=3, a<<n=[0, 1, 2, 3], diff=-1, n+=diff=2
n=2, a<<n=[0, 1, 2, 3, 2], diff=-1, n+=diff=1
n=1, a<<n=[0, 1, 2, 3, 2, 1], diff=-1, n+=diff=0
n=0, a<<n=[0, 1, 2, 3, 2, 1, 0], diff= 1, n+=diff=1
n=1, a<<n=[0, 1, 2, 3, 2, 1, 0, 1], diff= 1, n+=diff=2
n=2, a<<n=[0, 1, 2, 3, 2, 1, 0, 1, 2], diff= 1, n+=diff=3
#=> [0, 1, 2, 3, 2, 1, 0, 1, 2]
试试这个
def oscillate(a, b, step, num)
ramp_up = a.step(b, step).entries
ramp_down = ramp_up.drop(1).reverse.drop(1)
ramp_up.concat(ramp_down).cycle.take(num)
end
这是如何工作的?
- 创建
ramp_up
和ramp_down
数组 - 连接两个数组
-
cycle
返回一个不断重复的枚举器 -
take
具体化该枚举器中的num
元素。除了评论中建议的外,这不会重新计算任何内容。它只是具体化枚举器中的条目。