這裏做,讓你有點置身於慵懶序列的一種方式,但它肯定不是真的計算斐波那契序列的最佳方式。
鑑於Fibonacci序列的定義,我們可以看到它是通過將相同的規則重複應用於'(1 1)
的基本情況而構建的。 Clojure的功能iterate
聽起來這將是很好的這樣的:
user> (doc iterate)
-------------------------
clojure.core/iterate
([f x])
Returns a lazy sequence of x, (f x), (f (f x)) etc. f must be free of side-effects
所以對於我們的功能,我們想要的東西是需要到目前爲止,我們已經計算出的值,總結最近的兩次,並返回一個列表新價值和所有舊價值。
(fn [[x y & _ :as all]] (cons (+ x y) all))
參數列表這裏只是意味着x
和y
必將從作爲函數的參數傳遞的列表中的前兩個值,包含前兩個之後的所有參數列表將被綁定到_
,和作爲參數傳遞給函數的原始列表可以通過all
來引用。
現在,iterate
將返回一個無限序列的中間值,因此對於我們的情況,我們希望將它包裝在只返回我們感興趣的值的東西中;懶惰評估將會停止正在評估的整個無限序列。
(defn fib [n]
(nth (iterate (fn [[x y & _ :as all]] (cons (+ x y) all)) '(1 1)) (- n 2)))
還要注意,這會以與您的實施相反的順序返回結果;當然,用reverse
來解決這個問題很簡單。
編輯:或者確實如amalloy說,通過使用向量:
(defn fib [n]
(nth (iterate (fn [all]
(conj all (->> all (take-last 2) (apply +)))) [1 1])
(- n 2)))
更多的答案:http://codereview.stackexchange.com/questions/300/project-euler-problem-2-in-clojure – Jeremy