我正在制作一个带有列表和总和的程序。如果列表中的某些数字加起来,则返回true。否则,返回false。它似乎适用于某些情况但不适用于其他情况。例如,
如果我输入:
(numlist-sum '(5 9) 9)
它应该返回true,因为其中一个数字(9)等于总和(9)。但是,由于某种原因,它返回虚假。
我无法弄清问题是什么。请帮忙?
(define (numlist-sum? ls sum)
(if (null? ls) #t
(if (and (null? (cdr ls)) (equal? (car ls) sum)) #t
(if (equal? (car ls) sum) #t
(if (equal? (cdr ls) sum) #t
(if (equal? (apply + (car ls) (cdr ls)) sum) #t
#f))))))
答案 0 :(得分:0)
我会给你一些解决这个问题的提示(看起来像家庭作业)。首先编写一个生成列表所有可能子集的过程(例如,列表的power set)。例如:
(powerset '(1 2 3))
=> '(() (1) (2) (3) (1 2) (1 3) (2 3) (1 2 3))
通过上述程序(并且很容易找到算法,谷歌是你最好的朋友),只需遍历每个子列表并总结其值:
(apply + '(2 3))
=> 5
如果其中一个子列表的总和等于预期值,则返回#t
。如果总和中没有一个满足预期值,则返回#f
。
修改强>
我忘了提及,这是一个众所周知的问题 - 它是subset sum problem,它可以使用dynamic programming有效地解决(至少比生成功率集更有效)。但我认为这不是特别是这项功课的目标。
答案 1 :(得分:0)
这是一个解决方案,逐个检查每个元素,然后如果第一个元素不是总和,则向下递归列表。
(define (numlist-sum list sum)
(and (not (null? list))
(let ((head (car list)))
(cond ((number? head)
(or (= sum head)
(numlist-sum (cdr list) sum)))
((list? head)
(or (= sum (apply + head))
(numlist-sum (cdr list) sum)))
(else 'ill-formed-list)))))
另请注意,您的代码可以重写为:
(define (numlist-sum? ls sum)
(or (null? ls)
(if (and (null? (cdr ls)) (equal? (car ls) sum))
(equal? (car ls) sum)
(equal? (cdr ls) sum)
(equal? (apply + (car ls) (cdr ls)) sum)))
我会说使用'(如果使用#tt else ...)有点尴尬并且隐藏了代码的真正逻辑。