我正在通过Ruby做这个'序列生成器'Kata,不知何故我不知道如何实现这一点。但我试过了。请给我一些额外的帮助。谢谢!
编写生成器sequence_gen(JavaScript中的sequenceGen),给定序列的第一项将生成(可能)无限量的术语,其中每个后续术语是先前x术语的总和,其中x是数量初始参数(此类序列的例子是Fibonacci,Tribonacci和Lucas数字序列)。
示例:
fib = sequence_gen(0, 1) # returns an Enumerator
fib.next = 0 # first term (provided)
fib.next = 1 # second term (provided)
fib.next = 1 # third term (sum of first and second terms)
fib.next = 2 # fourth term (sum of second and third terms)
fib.next = 3 # fifth term (sum of third and fourth terms)
fib.next = 5 # sixth term (sum of fourth and fifth terms)
fib.next = 8 # seventh term (sum of fifth and sixth terms)
trib = sequence_gen(0,1,1) # returns an Enumerator
trib.next = 0 # first term (provided)
trib.next = 1 # second term (provided)
trib.next = 1 # third term (provided)
trib.next = 2 # fourth term (sum of first, second and third terms)
trib.next = 4 # fifth term (sum of second, third and fourth terms)
trib.next = 7 # sixth term (sum of third, fourth and fifth terms)
lucas = sequence_gen(2,1) # returns an Enumerator
lucas.take(10) = [2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
我的解决方案:
def sequence_gen(e, vs)
while true
begin
vs = e.next_values
return $!.result
end
y = yield(*vs)
e.feed y
end
end
最佳,
韩
答案 0 :(得分:2)
守则
您可以在枚举器中使用无限循环,如下所示:
def sequence_gen(*args)
Enumerator.new do |y|
args.each { |e| y << e }
loop do
y << sum = args.inject(:+)
args = args.drop(1).push(sum)
end
end
end
<强>解释强>
现在假设您已了解调查员的工作方式。我们假设我们正在使用sequence_gen(0,1)
args = [0,1]
的例子。考虑这一行:
args.each { |e| y << e }
序列的前几个术语将是传递给sequence_gen(0,1)
的参数,即0
和1
。这意味着我们首先需要按顺序产生参数0和1。这就是上面代码的作用。
无限循环
loop do
y << sum = args.inject(:+)
args = args.push(sum).drop(1)
end
此循环的目的是生成序列的其余部分。序列中的下一个数字是前两个参数的 sum ,即0
和1
,它们存储在数组args = [0,1]
中。我们可以使用inject(:+)
来轻松完成此操作。这使sum = 1
使用<<
通过y
获得了1
。这也意味着我们序列中的下一个数字也是args = [0,1]
。
目前0,1,1
,我们的序列为1,1
。为了获得序列中的下一个数字,我们需要对当前序列中的最后两个数字求和,即args
。我们通过转换push(sum)
来表示序列的最后两个数字。我们使用args = [0,1,1]
提供args = [0,1,1]
。然后从arg = [1,1]
sum = 2
中删除第一个元素。然后我们将这个新数组求和3, 5, 8
,这是我们序列中的下一个数字。创建这个新数组是由我们的循环的最后一行完成的。使用第一行完成求和。由于我们处于循环中,因此重复这些步骤,直到产生next
等。
take()
和next
做了什么?
在枚举器中定义无限循环时,您可以根据需要控制输出流。
y
获取下一个产生的值next
。在我们的示例中,根据枚举器中代码的顺序,调用0
一次指示y产生next
。再次呼叫1
会产生take(4)
。这是使用代码的第一部分(循环之前)完成的。然后循环保持并产生其余的值,理论上你可以永远这样做(因为你有一个无限循环)。
next
取得前4个元素。它类似于按顺序调用take(n)
四次,除了将生成的值保存到数组中。同样,因为我们有一个无限循环,理论上我们可以调用n
来获得我们想要的大puts 'The first seven terms of fib = sequence_gen(0, 1) are:'
fib = sequence_gen(0, 1) # returns an Enumerator
p fib.next #=> 0 # first term (provided)
p fib.next #=> 1 # second term (provided)
p fib.next #=> 1 # third term (sum of first and second terms)
p fib.next #=> 2 # fourth term (sum of second and third terms)
p fib.next #=> 3 # fifth term (sum of third and fourth terms)
p fib.next #=> 5 # sixth term (sum of fourth and fifth terms)
p fib.next #=> 8 # seventh term (sum of fifth and sixth terms)
puts
puts 'The first six terms of trib = sequence_gen(0,1,1) are:'
trib = sequence_gen(0,1,1) # returns an Enumerator
p trib.next #=> 0 # first term (provided)
p trib.next #=> 1 # second term (provided)
p trib.next #=> 1 # third term (provided)
p trib.next #=> 2 # fourth term (sum of first, second and third terms)
p trib.next #=> 4 # fifth term (sum of second, third and fourth terms)
p trib.next #=> 7 # sixth term (sum of third, fourth and fifth terms)
puts
puts 'The first ten terms of lucas = sequence_gen(2,1) are:'
lucas = sequence_gen(2,1) # returns an Enumerator
p lucas.take(10) #=> [2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
。
运行代码
然后使用 Enumerator 方法运行上述代码:
The first seven terms of fib = sequence_gen(0, 1) are:
0
1
1
2
3
5
8
The first six terms of trib = sequence_gen(0,1,1) are:
0
1
1
2
4
7
The first ten terms of lucas = sequence_gen(2,1) are:
[2, 1, 3, 4, 7, 11, 18, 29, 47, 76]
输出:
$('selector1')