Use map(v, reduce) to create Fibonacci sequence in R?

Viewed 294

I was wondering if we could use purrr's map and reduce to create to Fibonacci function akin to this one in JavaScript:

function fib(n){
  return new Array(n).fill(1).reduce((arr, _ ,i) => {
    arr.push((i <= 1) ? i : arr[i-2] + arr[i-1])
    return arr
  },[]) ;
}
console.log(fib(10))

I see answers here Fibonacci Sequence in R that use recursion but I was wondering if we could specifically use purrr's reduce and if so how?

3 Answers

I think purrr::accumulate() is better suited for the task:

n <- 10                                         # Desired number of values
purrr::accumulate( .init = c(0L,1L),            # Starting with (0,1)
                   rep(0,n),                    # Accumulate n times
                   ~c(.x,sum(.x))[2:3]          # (x,y) -> (x, y, x+y)[2:3]
                 ) %>% 
    purrr::map_int( `[`, 1 )                    # (x,y) -> x

# [1]  0  1  1  2  3  5  8 13 21 34 55

The key to this solution is to keep pairs of values throughout the accumulate() call: (0,1), (1,1), (1,2), etc., since you need two previous values to compute the new one.

This is followed by retrieving the first element of each pair.

How about this approach with map?

n<-10
map(n,function(x) round(((5+sqrt(5))/10) * ((1+sqrt(5))/2) ** (1:x-1)))
[[1]]
 [1]  1  1  2  3  5  8 13 21 34 55

Inspired by this answer. Obviously @Artem's answer is more in the spirit of the question. So hats off to them.

Here is a solution using reduce

fib <- function(n) reduce(rep(0,n-1), .f=function(x,y) c(x, x[length(x)-1] + x[length(x)]), .init=c(0,1))

fib(10)
# [1]  0  1  1  2  3  5  8 13 21 34 55

The good point of this solution is that it is very easy to interpret. Basically you just use the most basic functionality of reduce and write Fibonacci number in a function as how it is defined, nothing fancy.

Related