LISP功能可以打印出最多N个数字的斐波纳契序列

时间:2017-01-27 02:25:53

标签: functional-programming lisp common-lisp

我必须编写计算N个Fibonacci数的代码(其中N是函数参数)。我是LISP的新手,我正在努力学习语法。这就是我到目前为止......我觉得它很接近。

(defun fib (n)
(if (or (= n 1) (= n 2))
(print 1))
(print (+ (fib (- n 1))(fib (- n 2)))))
;;;;It should output like so:
(fib 0)
()
(fib 2)
( 1 1 )
(fib 6)
( 1 1 2 3 5 8 )

有人能帮我整理一下我的功能吗?提前谢谢!

3 个答案:

答案 0 :(得分:2)

如果您希望(1 1)评估REPL中的(fib 2),那么您不希望打印任何内容,只需要返回列表(1 1)即可。

;; using recursion. 
(defun fib (limit)
  (labels ((helper (n a b)
             (if (> n limit)
                 '()
                 (cons a (helper (1+ n) b (+ a b))))))
    (helper 0 0 1)))

;; using tail recursion. Usually tail call optimized when 
;; compiled, but it's not a requirement in the standard.
(defun fib (limit)
  (labels ((helper (n a b acc)
             (if (> n limit)
                 (nreverse acc)
                 (helper (1+ n) b (+ a b) (cons a acc)))))
    (helper 0 0 1 '())))

;; Using loop. Never blows stack.
(defun fib (limit)
  (loop :for a := 0 :then b
        :and b := 1 :then (+ a b)        
        :repeat limit
        :collect a))

我认为所有这些都具有相同的可读性,因此没有理由不选择任何实现中最安全的loop版本。

请注意,第一个fibonacci数字为0,我的代码反映了该数字。

答案 1 :(得分:0)

你这样做的方式是tree recursive,它的运行时间会呈指数级增长。该链接具有有效的替代品。但是,如果你想保留整个序列,你可以做类似的事情,

(defun fib (num)
  (let (seq)
    (labels ((helper (n)                                  ; define local helper function
               (when (<= n num)                           ; stop when reached NUM
                 (if (< n 3) (push 1 seq)
                     (push (+ (car seq) (cadr seq)) seq)) ; sum of previous 2
                 (helper (1+ n)))))                       ; recurse
      (helper 1))                                         ; start from first fib number
    (nreverse seq)))                                      ; reverse the result

答案 2 :(得分:0)

这是另一种可以使用辅助程序并继续解决问题的方法。

此过程是尾递归但需要反转累积的斐波纳契数列表。

(define (fib n)
  (define (aux n a b k)
    (if (zero? n)
        (k (list a))
        (aux (sub1 n)
             b
             (+ a b)
             (lambda (rest) (k (cons a rest))))))
  (aux n 0 1 identity))

(fib 0)  ;; => '(0)
(fib 1)  ;; => '(0 1)
(fib 2)  ;; => '(0 1 1)
(fib 10) ;; => '(0 1 1 2 3 5 8 13 21 34 55)

这里的代码是球拍,但你可以相对轻松地将它翻译成Lisp。