使用lisp添加两个列表

时间:2014-04-26 18:00:37

标签: lisp common-lisp

我喜欢使用lisp的两个列表。 例如:

(1 2 3 4 5) + ( 9 9 9 9 9) = (1 1 2 3 4 4)

但是,当我使用

时,我得到(10 11 12 13 14)
(add '(1 2 3 4 5) '(9 9 9 9 9))   

(defun add (x y)
  (setf return-value '())
  (loop for i from 0 to (- (length x) 1)
        do (setf return-value (cons (+ (nth i l) (nth i y)) return-value)))
  (reverse return-value))

这意味着它没有在另一方使用一笔款项。

你能帮忙吗? 感谢

2 个答案:

答案 0 :(得分:1)

您的代码存在多个问题......您应该手动编写此代码。因此,您需要从最后一位开始,并从右到左处理数字。除此之外,你有一个变异的l,你的return-value不是你职能的本地。

我改编了一段时间以前在Scheme中写过的solution。它可能不是Common Lisp的惯用语,但它在这一点上应该是有用的:

(defun add (l1 l2)
  (flet ((car0 (lst) (if (null lst) 0 (car lst))))
    (labels ((lp (l1 l2 carry res)
                (if (and (null l1) (null l2) (= 0 carry)) 
                  res
                  (let* ((d1 (car0 l1))        
                         (d2 (car0 l2)) 
                         (ad (+ d1 d2 carry))  
                         (dn (mod ad 10)))
                    (lp (cdr l1) (cdr l2) (truncate (- ad dn) 10) (cons dn res))))))
      (lp (reverse l1) (reverse l2) 0 nil))))

然后

? (add '(1 2 3 4 5) '( 9 9 9 9 9))
(1 1 2 3 4 4)

希望这有帮助。

答案 1 :(得分:0)

这看起来像是一个家庭作业问题,所以我不打算提供一个固定的解决方案。

你似乎错过的是Lisp并不知道你正在尝试实现“使用10进位加载”。另外,想想你如何手工添加。当我计算999 + 001时,我不能一次只能处理一个数字,因为单位的进位一直传播到10 ^ 4列。

我建议你先写一个函数

(defun add-seqs-special (seq1 seq2 base)
   "Add together two sequences of numbers, assumed to be of the same length.
    Each element is assumed to be at most BASE, the base of the number system
    in which we're working. Moreover, we assume that the addition doesn't
    overflow."
   ;; Exercise for reader...
   )

然后编写一个单独的函数,强制向量的长度相同,并在每个向量的开头添加零(以确保添加不会耗尽地点)。

add-seqs-special的实施需要从右端开始工作,一次加两个数字,然后累加一个“进位”数字,如果它们的总和大于base(或硬编码base = 10,但它不会使程序更容易编写)

要获取序列的元素,可以使用elt。如果将列表作为参数传递,这将不会特别有效,因为列表对于随机访问来说很慢。一旦你编写了这段代码,你就会发现你并没有真正做随机访问。实际上,您需要向后迭代列表。啊啊!所以现在你可以编写一个新版本,它以反转输入开始,然后继续CDR

事实上,这会更好,因为很容易处理该版本空间不足的问题。但是,你似乎对Lisp来说还是一个新手,所以我真的建议首先编写随机访问版本:如果你已经习惯了C或Python或其他什么,它就更容易表达。

最后,有一种完全不同的方式。你正在添加数字,Lisp已经有任意精度算术,所以你可以改为编写两个函数:digits-to-numbernumber-to-digits,并在它们之间使用+! (如果您过去看过Project Euler问题,那么您可能已经用至少一种语言编写了这些函数)