conj - Implementar fibonacci en Clojure usando map/reduce
list conj clojure (3)
¿Es posible implementar la serie de fibonacci en Clojure de manera eficiente usando reduce
? ¿Qué contendría el "acumulador"?
Imagino que tendrá que ser flojo. Es obvio cómo hacerlo usando recursion o loop / recur.
Puede usar un par de valores sucesivos de Fibonacci como acumulador, de la siguiente manera:
(reduce
(fn [[a b] _] [b (+ a b)]) ; function to calculate the next pair of values
[0 1] ; initial pair of fibonnaci numbers
(range 10)) ; a seq to specify how many iterations you want
=> [55 89]
Esto no es particularmente eficiente debido a la creación de muchos pares intermedios y el uso de la secuencia de rango superfluo para manejar el número correcto de iteraciones, pero es O (n) desde una perspectiva algorítmica (es decir, lo mismo que la solución iterativa eficiente, y mucho mejor que el ingenuo recursivo).
No usar mapa / reducir, pero iterar puede evitar la recursión también.
(defn iter [[x y]]
(vector y (+ x y)))
(nth (iterate iter [0 1]) 10000)
Esto lleva 21 ms en Intel 2.4 Ghz
En la misma máquina, reduce lleva 61 mseg. No estoy seguro de por qué iterar es más rápido.
(time (reduce
(fn [[a b] _] [b (+ a b)]) ; function to calculate the next pair of values
[0 1] ; initial pair of fibonnaci numbers
(range 10000)))
Esto le dará un vector de los primeros 1000 números de Fibonacci (tamaño del range
+ 2), manejando el segundo argumento de la función ( range
) como el contador:
(reduce
(fn [a b] (conj a (+'' (last a) (last (butlast a)))))
[0 1]
(range 998))