Common Lisp:使用(let)来评估递归函数

时间:2015-06-19 00:50:27

标签: recursion common-lisp subset-sum

所以我写了一些东西,给出一个正整数列表返回一个最大子集和。但是,我想使用(let)以便我使代码更有效。我想知道是否或如何可能。

(defun subset-sum1 (numbers capacity)
  (subset-sum numbers capacity 0))

(defun subset-sum (numbers capacity counter) 
  (cond ((null numbers) counter)
        ((= counter capacity) counter) ;; return if counter 'hits' the capacity
        ((< capacity (+ (car numbers) counter))
         (subset-sum (cdr numbers) capacity counter)) ;; cdr if car branch exceeds capacity
        ((<= (subset-sum (cdr numbers) capacity counter)
             (subset-sum (cdr numbers) capacity (+ (car numbers) counter)))
         (subset-sum (cdr numbers) capacity (+ (car numbers) counter))) ;; choose car
        (t (subset-sum (cdr numbers) capacity counter)))) ;; choose cdr

以上代码在常见的lisp中运行良好。但是,我想做类似下面的事情,因为我觉得使用let会使代码变得更好。但是我写的内容进入无限循环:( 这是一个介绍AI课程的作业......请帮助新手!

(defun subset-sum (numbers capacity counter)
  (let ((exclude (subset-sum (cdr numbers) capacity counter))
   (include (subset-sum (cdr numbers) capacity (+ (car numbers) counter))))
     (cond ((null numbers) counter)
       ((= counter capacity) counter)
       ((< capacity (+ (car numbers) counter)) exclude)
       ((<= exclude include) include)
       (t (exclude)))))

1 个答案:

答案 0 :(得分:1)

由于这些行,你得到一个无限循环:

(defun subset-sum (numbers capacity counter)
  (let ((exclude (subset-sum (cdr numbers) capacity counter))

你一直在递归地调用 subset-sum ,它永远不会终止。即使你到达列表的末尾,数字(),你仍然继续,因为(cdr'(())是的'()即可。您通过检查(空号码)来处理原始内容(尽管使用(endp numbers)可能更惯用)。现在你可以做类似的事情:

(defun subset-sum (numbers capacity counter)
  (if (endp numbers)
    counter
    (let ((exclude (subset-sum (cdr numbers) capacity counter))
          ;...
         )
      (cond ; ...
          ))))