问题
So, I saw someone using the reduce method to calculate the Fibonacci sequence. Here is his idea: (1,0) , (1,1) , (2,1) , (3,2) , (5,3) corresponds to 1, 1, 2, 3, 5, 8, 13, 21 .......
and the code looks like this
def fib_reduce(n):
initial =(1,0)
dummy = range(n)
fib_n = reduce(lambda prev ,b : (prev[0] + prev[1], prev[0]),
dummy,
initial)
return fib_n[0]
I understand the (prev[0] + prev[1] , prev[0])
which is like
a, b = b, b + a
.
However, I don't understand what this b
stands for ?
May someone please explain this b
?
回答1:
Repeatedly applying a function using reduce
This answer suggests writing up your own function repeated
to repeatedly apply a function, rather than calling reduce
with a dummy second argument.
We still use reduce
, but in a more functional manner and with itertools.repeat
.
from itertools import repeat
from functools import reduce
def repeated(func, n):
def apply(x, f):
return f(x)
def ret(x):
return reduce(apply, repeat(func, n), x)
return ret
def fibonacci(n):
get_next_pair = lambda p: (sum(p), p[0])
first_pair = (1, 0)
return repeated(get_next_pair, n)(first_pair)[1]
print(fibonacci(0), fibonacci(1), fibonacci(11))
# 0 1 89
Repeatedly apply a linear function using linear algebra
The function lambda a,b: b,a+b
which you want to apply happens to be a linear function. It can be represented by a 2*2 matrix. Repeatedly applying the function to a two-element tuple is the same as repeatedly multiplying a two-element vector by the matrix.
This is cool, because taking the power of a matrix is much, much faster than repeatedly applying a function.
import numpy as np
def fibonacci(n):
return np.linalg.matrix_power(np.array([[0, 1],[1,1]]), n).dot(np.array([0,1]))[0]
print(fibonacci(0), fibonacci(1), fibonacci(11))
# 0 1 89
If you don't like one-liners, here is the same function decomposed on a few lines with more explicit variable names:
import numpy as np
def fibonacci(n):
next_pair_matrix = np.array([[0, 1],[1,1]])
matrix_to_the_nth = np.linalg.matrix_power(next_pair_matrix, n)
first_pair_vector = np.array([0,1])
nth_pair_vector = matrix_to_the_nth.dot(first_pair_vector)
return nth_pair_vector[0]
print(fibonacci(0), fibonacci(1), fibonacci(11))
# 0 1 89
来源:https://stackoverflow.com/questions/64888397/fibonacci-sequence-using-reduce-method