2015-06-19 2 views
1

Итак, я написал что-то, что возвращает максимальную сумму подмножества, заданную списком положительных целых чисел. Однако я хотел бы использовать (let), чтобы сделать код более эффективным. Я хотел бы знать, если и как это возможно.Common Lisp: Использование (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 

Приведенный выше код работает нормально в общем свете. Но я хотел бы сделать что-то вроде ниже, потому что я чувствую, что использование 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

Вы получаете бесконечный цикл из этих строк:

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

вы продолжаете называть подмножеством-сумму рекурсивны, и она никогда не прекращается. Даже когда вы дойдете до конца списка, и номер является (), вы продолжаете идти, потому что (cdr '()) is '(). Вы обработали это в оригинале, проверив (нулевые цифры) (хотя было бы более идиоматично использовать (номера endp)). Теперь вы можете сделать что-то вроде:

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

Теперь это работает. Поэтому я понимаю, что хочу поставить basecase перед использованием условного цикла с let. Огромное спасибо! –

Смежные вопросы