Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 斐波那契单线性_Ruby_Fibonacci - Fatal编程技术网

Ruby 斐波那契单线性

Ruby 斐波那契单线性,ruby,fibonacci,Ruby,Fibonacci,我正在尝试用Ruby one liners解决来自的问题,我很好奇是否有更优雅的解决方案: 斐波那契序列中的每个新项都是通过将前两项相加生成的。从1和2开始,前10个术语将是: 1、2、3、5、8、13、21、34、55、89 通过考虑Fibonacci序列中值不超过400万的项,求偶数值项之和 以下是我的Ruby单线解决方案: (1..32).inject([0,1]) {|arr, i| (arr << arr[-1] + arr[-2] if arr[-1] + arr[-2]

我正在尝试用Ruby one liners解决来自的问题,我很好奇是否有更优雅的解决方案:

斐波那契序列中的每个新项都是通过将前两项相加生成的。从1和2开始,前10个术语将是:

1、2、3、5、8、13、21、34、55、89

通过考虑Fibonacci序列中值不超过400万的项,求偶数值项之和

以下是我的Ruby单线解决方案:

(1..32).inject([0,1]) {|arr, i| (arr << arr[-1] + arr[-2] if arr[-1] + arr[-2] <= 4000000) || arr}.inject(0) {|total, i| total += i.even? ? i : 0}

(1..32).使用Ruby 1.9枚举器注入([0,1]){arr,i|(arr:

fib = Enumerator.new do |yielder|
  i = 0
  j = 1
  loop do
    i, j = j, i + j
    yielder.yield i
  end
end

p fib.take_while { |n| n <= 4E6 }
# => [1, 1, 2 ... 1346269, 2178309, 3524578]
fib=Enumerator.new do | yielder|
i=0
j=1
环道
i、 j=j,i+j
一号
结束
结束
p fib.take_while{n|n[1,1,2…1346269,2178309,3524578]
作为一行:

p Enumerator.new { |yielder| i, j = 0, 1; loop {i, j = j, i + j; yielder.yield i} }.take_while { |n| n <= 4E6}

p Enumerator.new{yielder | i,j=0,1;loop{i,j=j,i+j;yielder.yield i}。在{n | n时,我最喜欢的解决方案是使用散列,其值可以由匿名函数确定:

fibonacci = Hash.new{ |h,k| h[k] = k < 2 ? k : h[k-1] + h[k-2] }

fibonacci[6]  # => 8 
fibonacci[50] # => 12586269025
fibonacci=Hash.new{h,k | h[k]=k<2?k:h[k-1]+h[k-2]}
斐波那契[6]#=>8
斐波那契[50]#=>12586269025

这是一个“真正的”单行程序,非常类似于Ruby。

基于Alex的哈希,这可能会让你失明,但它是一行,没有分号,并且消除了范围依赖性。instance\u eval技巧对于单行程序和高尔夫非常有用,尽管它是可怕的Ruby

Hash.new{|h,k|h[k]=k<2?k:h[k-1]+h[k-2]}.update(sum: 0,1=>1).instance_eval {self[:sum]+= self[keys.last+1].even? ? self[keys.last] : 0 while values.last < 4E6 || puts(fetch :sum)}
Hash.new{h,k{h[k]=k1.instance_eval{self[:sum]+=self[keys.last+1]。偶数??self[keys.last]:0 while values.last<4E6 | | put(fetch:sum)}
产出:4613732

我警告过你这太可怕了。我不能让它在不使用分号的情况下返回值,对不起。

这个怎么样

(((1 + 5 ** 0.5) / 2) ** 35 / 5 ** 0.5 - 0.5).to_i / 2
(解释一下。)

我最喜欢的是:

def fib(n)
  (0..n).inject([1,0]) { |(a,b), _| [b, a+b] }[0]
end

从亚历克斯的回答中得到启发:

# Ruby 1.8.7
f = lambda { |x| x < 2 ? x : f.call(x-1) + f.call(x-2) }
puts f.call(6)   #=> 8

# Ruby 1.9.2
f = ->(x){ x < 2 ? x : f[x-1] + f[x-2] }
puts f[6]        #=> 8
#Ruby 1.8.7
f=lambda{x | x<2?x:f.call(x-1)+f.call(x-2)}
将f.call(6)#=>8
#Ruby 1.9.2
f=->(x){x<2?x:f[x-1]+f[x-2]}
将f[6]#=>8

这是一个针对Euler prob#2的单线ruby解决方案


(0..4000000)。在ruby 2.0中使用新的lazy,你可以这样写

puts (1..Float::INFINITY).lazy.map{|n| (0..n).inject([1,0]) {|(a,b), _| [b, a+b]}[0] }.take_while{|n| n < 4000000}.select{|x| x % 2 == 0}.reduce(:+)
put(1..Float::INFINITY).lazy.map{n}(0..n).injection([1,0]){{a,b),{b,a+b]}[0]}.在{n{4000000}时取{u.选择{x}x%2==0}.减少(:+)

这是一个ruby 2.0解决方案,不使用inject/reduce,它不是懒惰的:

(1..Float::INFINITY).
  lazy.
  with_object([0,1]).
  map { |x, last| last[1] = last[0] + (last[0] = last[1]) }.
  select { |x| x % 2 == 0 }.
  take_while { |x| x < 4_000_000 }.
  reduce(&:+)
(1..Float::INFINITY)。
懒惰。
使用_对象([0,1])。
映射{x,last{last[1]=last[0]+(last[0]=last[1])。
选择{| x | x%2==0}。
当{x{x<4_000}时取{u。
减少(&:+)
我并不特别喜欢fibonacci生成器,因为它不包含初始值0。此解决方案还利用了第一个奇数F3(此序列生成器中的F1)

一个更干净(斐波那契式)和正确(按照Liber-Abaci的定义)的解决方案是:

(1..Float::INFINITY).
  lazy.
  with_object([0,1]).
  map { |x, last| last[1] = last[0] + (last[0] = last[1]);last[0] }.
  select { |x| x % 2 == 0 }.
  take_while { |x| x < 4_000_000 }.
  reduce(&:+)
(1..Float::INFINITY)。
懒惰。
使用_对象([0,1])。
映射{x,last{last[1]=last[0]+(last[0]=last[1]);last[0]}。
选择{| x | x%2==0}。
当{x{x<4_000}时取{u。
减少(&:+)
这个解决方案包括一个分号,但我不知道这样使用时是否算数:)

[更新]

这里有一个合适的Fibonacci生成器(从0开始)解决方案,没有分号(顺便说一句,这是javascript分号吗?!?)

(1..Float::INFINITY)。
懒惰。
使用_对象([0,1])。
映射{x,last{last[0]。点击{last[1]=last[0]+(last[0]=last[1])}。
选择{| x | x%2==0}。
当{x{x<4_000}时取{u。
减少(&:+)

我意识到这是一个古老的问题,已被归类为已回答的问题,但没有人能在一个块中解决这个问题,没有人能在一行一个块中给出偶数值项的总和,并且没有分号(刚刚注意到waynes确实用一行来解决问题,但我认为一个块解决方案可能会很好地响应aroth)。以下是一个解决方案:

(1..Float::INFINITY).inject([0,1,0]){|a| if a[0]+a[1] < 4000000 then [a[1],a[0]+a[1],(a[0]+a[1]).even? ? a[2] + (a[0]+a[1]) : a[2]] else break a[2] end }
(1..Float::INFINITY).injection([0,1,0]){| a |如果a[0]+a[1]<4000000,那么[a[1],a[0]+a[1],(a[0]+a[1])。偶数??a[2]+(a[0]+a[1]):a[2]]否则会中断a[2]结束]
对于带有一个分号的稍微清晰的版本

(1..Float::INFINITY).inject([0,1,0]){|a| sum=a[0]+a[1]; if sum < 4000000 then [a[1],sum,sum.even? ? a[2] + sum : a[2]] else break a[2] end }
(1..Float::INFINITY).注入([0,1,0]){| a | sum=a[0]+a[1];如果sum<4000000,则[a[1],sum,sum.偶数??a[2]+sum:a[2]]否则中断a[2]end}
我想我也会解释一下,数组中有三条信息(每次迭代时都是
a
)第一个fibonacci数,第二个fibonacci数和偶数项之和。记住这一点,我认为这段代码非常清楚


应该注意的是,这与clems基本相同,只是在一个块中

返回的正确值最多为
Fib(70)
,除此之外只是一个近似值。但速度非常快:

(((Math.sqrt(5.0) + 1.0) / 2.0)**n / Math.sqrt(5.0) + 0.5).floor

(请参阅以获取解释)

作为上述答案的总结解决方案,并附上我的简短补充:

32.
  times.
  lazy.
  with_object([0, 1]).map { |_, fib| fib[1] = fib[0] + fib[0] = fib[1]; fib[0] }.
  take_while(&:>.to_proc.curry(2)[4*10**6]).
  select(&:even?).
  inject(:+)
我真的不喜欢咖喱的样子,但我不想让它看起来和其他答案相似。备选方案
take\u while
仅针对这种情况:

  take_while { |value| value < 4*10**6 }.
在{| value | value<4*10**6}时取。

(1..32).inject([0,1]){fib | fib这是我的一行代码,当我们得到方法返回时,
@fib
表被填充

@fib=[0,1];def fib num; return 0 if num < 0; @fib[num]||=fib(num-1)+fib(num-2);end
@fib=[0,1];def fib num;如果num<0,则返回0;@fib[num]| |=fib(num-1)+fib(num-2);结束

简单优雅是最好的方式,对吗

a0 = 1; a1 = 1; 20.times {|i| b = a0 + a1; a0 = a1; a1 = b; puts b };
输出:

2
3
5
8
13
21
34
55
89
144
233
377
610
987
1597
2584
4181
6765
10946
17711
=> 20

我现在可以想出4种方法来实现斐波那契目标

  • 使用刺刀lambda:
  • 这将评估10个系列。但如果要获取用户编号:

    puts 'Fibonacci Sequence in a Line: ', ->(a=1, b=0) { gets.to_i.times.collect { (a, b = b, a + b)[0] } }.call
    
  • 使用
    点击
    方法:
  • 使用
    reduce/inject
    方法:
  • 使用
    带有对象的每个\u
    映射。带有对象的方法:
  • 注意:如果您没有Ruby 2.4+,您可能无法使用ha
    0
    1
    1
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987
    1597
    2584
    4181
    6765
    10946
    
    @fib=[0,1];def fib num; return 0 if num < 0; @fib[num]||=fib(num-1)+fib(num-2);end
    
    a0 = 1; a1 = 1; 20.times {|i| b = a0 + a1; a0 = a1; a1 = b; puts b };
    
    2
    3
    5
    8
    13
    21
    34
    55
    89
    144
    233
    377
    610
    987
    1597
    2584
    4181
    6765
    10946
    17711
    => 20
    
    puts 'Fibonacci Sequence in a Line: ', ->(a=1, b=0) { 10.times.collect { (a, b = b, a + b)[0] } }.call
    
    puts 'Fibonacci Sequence in a Line: ', ->(a=1, b=0) { gets.to_i.times.collect { (a, b = b, a + b)[0] } }.call
    
    [0, 1].tap { |a| 10.times { a.push(a[-1] + a[-2]) } }
    
    (1..10).reduce([0, 1]) { |a| a.push(a.last(2).sum) }
    
    10.times.reduce([0, 1]) { |a| a.push(a.last(2).sum) }
    
    10.times.each_with_object([0, 1]) { |_, a| a.push(a.last(2).sum) }
    
    [0, 1].tap { |a| until (s = a.last(2).sum) > 4_000_000 do a.push(s) end }.select(&:even?).sum
    
    [0, 1].tap { |a| loop while a.push(a.last(2).sum)[-1] < 4_000_000 }.tap(&:pop).select(&:even?).sum