Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/23.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,我需要改进这个算法的性能。我相信答案在于皮萨诺时期的应用 该算法必须返回从f(m)到f(n)的fib数总和的最后一位 以下是我到目前为止的情况: def fib(n) a = [] a << 0 << 1 (n+1).times do |i| a << a[-1] + a[-2] end a[n] end def fib_partial_sum(m, n) if n == m

我需要改进这个算法的性能。我相信答案在于皮萨诺时期的应用

该算法必须返回从f(m)到f(n)的fib数总和的最后一位

以下是我到目前为止的情况:

def fib(n)
    a = []
    a << 0 << 1
    (n+1).times do |i|
        a << a[-1] + a[-2]
    end
     a[n]
end


def fib_partial_sum(m, n)
    if n == m
        fib(m) % 10
    else
        m = fib(m + 1) - 1
        n = fib(n + 2) - 1
        (n - m) % 10
    end
end

if __FILE__ == $0
  m, n = gets.split().map(&:to_i)
  puts "#{fib_partial_sum(m, n)}"
end
def fib(n)
a=[]

a以下只需要一次从零到最多
[n,m+60].min之间的数字传递,其中
m..n
是感兴趣的范围,并且具有最小的内存需求。它利用了@nloveladyallen的观察结果,即斐波那契数的最后一位具有60的周期性

代码

def fib_last(m,n)
  n -= 60*((n-m)/60)   
  fib_sum(m,n) % 10
end

def fib_sum(m,n)
  return nil if m < 0 || m > n
  return n if n < 2
  next_to_last, last = fib(m-1)
  (m..n).reduce(0) do |tot,_|
    current = next_to_last + last
    next_to_last = last
    last = current
    tot + current
  end
end

def fib(m)
  next_to_last, last = -1, 1
  0.upto(m).each do |n|
    current = next_to_last + last
    next_to_last, last = last, current
  end
  [next_to_last, last]
end
m, n = 6, 12
(n+1).times { |i| puts "#{i}: #{fib(i)}" }
0:  [0,    0]
1:  [0,    1]
2:  [1,    1]
3:  [1,    2]
4:  [2,    3]
5:  [3,    5]
6:  [5,    8]
7:  [8,   13]
8:  [13,  21]
9:  [21,  34]
10: [34,  55]
11: [55,  89]
12: [89, 144]

fib_last(6,12) #=> 4 (fib_sum(6,12) #=> 8 + 13 + 21 + 34 + 55 + 89 + 144 = 364)
fib_last(1,2)  #=> 2 (fib_sum(1,2)  #=> 1 + 1 = 2)
fib_last(1,3)  #=> 4 (fib_sum(1,3)  #=> 1 + 1 + 2 = 4) 
fib_last(1,4)  #=> 7 (fib_sum(1,4)  #=> 1 + 1 + 2 + 3 = 7)
fib_last(2,3)  #=> 3 (fib_sum(2,3)  #=> 1 + 2 = 3)

这是一个很好的问题解决方案,它通过了所有的时间和内存限制。 这样你就不必计算一个大于f(60)的fib数值。它可以有效地处理非常大的输入

def fib(n)
    a, b = 0, 1
    (n-1).times do
        a, b = b, (a + b) % 10
    end
    b
end

def fib_partial_sum(m, n)
    if n == m
        fib(m % 60)
    else
        m = m % 60
        n = n % 60

        m = fib(m + 1) - 1
        n = fib(n + 2) - 1

        (n - m) % 10
    end
end

if __FILE__ == $0
    m, n = gets.split().map(&:to_i)
    puts "#{fib_partial_sum(m, n)}"
end

(最大使用时间:0.05/5.00,最大使用内存:8699904/536870912。)

是否应启用此选项?除非是代码不起作用。标题表明是这样,但质疑性能。顺便问一下,您有理由在
fib
上使用数组吗?你的函数基本上返回一个数字;使用两个临时变量而不是一个数组(它有分配/重新分配和垃圾收集的开销,还有更大的内存占用),可以很容易地做到这一点。斐波那契数的最后数字每60个数字重复一次,因此可以用n%60和m%60替换n和m。(你真的可以只使用最后一个数字序列的数组,但你可能正在尝试学习算法技术,所以这可能不是你想要的。)@matthewalexander它在输入上失败了,因为你只更改了
fib_partial_sum
中的
else
,在本例中n=m。将
if
主体更改为
fib(m%60)
,它应该可以工作。
“非常感谢您的任何见解。”
也是不可取的。虽然对帮助表示感谢很好,但作为一本参考书而不是一个讨论板,有一种更正式的立场。把它想象成一本教科书或食谱,然后相应地写下来。欢迎一些熟悉和友好,但签名、问候和感谢不会被删除。输入1失败,输入1失败,输入1失败,输入3我卡里-非常感谢您的努力,请查看我的最新更新,了解我所寻求的解决方案。我有严格的时间和内存限制,我修改了代码,加入了@nloveladyallen对斐波那契数最后一位数字周期性的观察。
def fib(n)
    a, b = 0, 1
    (n-1).times do
        a, b = b, (a + b) % 10
    end
    b
end

def fib_partial_sum(m, n)
    if n == m
        fib(m % 60)
    else
        m = m % 60
        n = n % 60

        m = fib(m + 1) - 1
        n = fib(n + 2) - 1

        (n - m) % 10
    end
end

if __FILE__ == $0
    m, n = gets.split().map(&:to_i)
    puts "#{fib_partial_sum(m, n)}"
end