The lisp-way to solve Fibonnaci

前端 未结 14 1483
别那么骄傲
别那么骄傲 2021-02-08 07:17

I wanted to try and learn Lisp, but I very quickly gave up. I figured I\'d try again. I\'m looking at Problem 2 on Project Euler - finding the sum of all even Fibonacci numbers

14条回答
  •  北恋
    北恋 (楼主)
    2021-02-08 08:14

    Memoization is a way to cache results to a function, to avoid re-calculating the intermediary results over and over. Memoization basically means the first time you call a function with some args, calculate the answer and return it, and cache that answer; for subsequent calls to a function with those same args, just return the cached value.

    In Lisp you can easily use higher-order functions and a macro to transparently memoize a function. Clojure has memoize as an included standard function. Also look on page 65 of On Lisp for a Common Lisp implementation of memoize. Here it is in Clojure:

    (defn fib-naive [i]
      (if (or (= i 1) (= i 2))
        1
        (+ (fib-naive (- i 1)) (fib-naive (- i 2)))))
    
    (def fib-memo
         (memoize (fn [i]
                    (if (or (= i 1) (= i 2))
                      1
                      (+ (fib-memo (- i 1)) (fib-memo (- i 2)))))))
    
    user> (time (fib-naive 30))
    "Elapsed time: 455.857987 msecs"
    832040
    user> (time (fib-memo 30))
    "Elapsed time: 0.415264 msecs"
    832040
    user> 
    

    This can still cause a stack overflow if you call it on a large integer. e.g. immediately doing (fib 10000) will blow the stack because it still has to recurse very deeply (once). But if you prime the cache first, it no longer has to recurse deeply and this can be avoided. Simply doing this first (in Clojure):

    (dorun (map fib-memo (range 1 10000)))
    

    will be enough to then let you do (fib 10000) without problems.

    (The specific subject of calculating Fibonacci numbers came up recently on the Clojure mailing list. There's a solution there based on the Lucas numbers which I don't understand in the slightest, but which is supposedly 40 times faster than a naive algorithm.)

提交回复
热议问题