0

我需要编写一个 lisp 函数,将 x 添加到列表的第 n 项。例如,(add 5 2 '(3 1 4 6 7))返回(3 6 4 6 7).

选择 nthitem 是

(defun nthitem (n list)
  (cond ((equal n 1) (car list))
        (t (nthitem (-n 1) (cdr list)))))

并将 x 添加到列表中是:

(defun addto (x list)
  (cond ((null list) nil)
        (t (cons (+ x (car list)) 
                 (addto x (cdr list))))))

但我不能将这两者结合在一起。

4

4 回答 4

1

我们没有得到nreconc足够的使用。这是一个基于doand的解决方案reconc。这个想法是遍历列表,以相反的顺序从列表中累积元素,直到到达需要替换的元素的位置。然后你把这些位粘在一起。也就是说,您反转您一直在积累的列表,并将其附加到由新元素和尾部构建的列表中。

(defun add (number index list)
  (do ((head '() (list* (first tail) head))
       (tail list (rest tail))
       (index index (1- index)))
      ((zerop index)
       (nreconc head (list* (+ number (first tail))
                            (rest tail))))))
CL-USER> (add 5 2 '(3 1 4 6 7))
(3 1 9 6 7)

值得看看这些值如何随时间变化。让我们考虑一个具有更多数字的示例,并查看每次迭代中headtail和的值:index

CL-USER> (add 90 5 '(0 1 2 3 4 5 6 7 8 9))
(0 1 2 3 4 95 6 7 8 9)

head: ()
tail: (0 1 2 3 4 5 6 7 8 9)
index: 5

head: (0)
tail: (1 2 3 4 5 6 7 8 9)
index: 4

head: (1 0)
tail: (2 3 4 5 6 7 8 9)
index: 3

head: (2 1 0)
tail: (3 4 5 6 7 8 9)
index: 2

head: (3 2 1 0)
tail: (4 5 6 7 8 9)
index: 1

head: (4 3 2 1 0)
tail: (5 6 7 8 9)
index: 0

一旦我们得到0,我们可以通过将其与 相加并将其放在一起来获得最终结果的其余部分,即number(car tail)(cdr tail)

(list* (+ (car tail) number) (cdr tail)

产生

(95 6 7 8 9)

然后使用nreconc(4 3 2 1 0)(95 6 7 8 9)(0 1 2 3 4 95 6 7 8 9),即

(nreconc (list 4 3 2 1 0) '(95 6 7 8 9))
;=> (0 1 2 3 4 95 6 7 8 9)

现在,如果由于某种原因您不能使用do,例如,这是一个家庭作业,那么该跟踪仍应为您提供足够的信息来编写带有累加器的直接递归版本。但是,无论如何,您仍然需要能够reverse(或nreverse)一个列表,以及append(或nconc)一些列表在一起(或,组合,revappendnreconc)。

于 2013-10-23T19:56:54.910 回答
0

您有主要的格式问题,并且在某些地方的运算符之间缺少空间。一定要使用像 Emacs 或 Kate 那样进行括号匹配的编辑器。

addto只是为了向您展示如何在不改变功能的情况下将这两者结合起来

(defun addto (x n list)
  (cond ((null list) nil)
        (t (cons (+ x (car list)) 
                 (addto x (- n 1) (cdr list))))))

因此,除了基本情况外,您的代码还应该有两种情况。一个(= n 1)因为你从 1 而不是 0 开始计数,这是你今天的默认情况,一个不添加 . 的car地方,只需在cdr. 祝你好运

于 2013-10-23T19:34:12.997 回答
0

您只需要nthsetf

emacs -Q,然后评估以下内容:

(defun add-to-nth (x n ys)
  (when ys (setf (nth n ys) (+ x (nth n ys)))))

(setq foobar  '(1 2 3 4 5))
(add-to-nth 42 1 foobar)

C-h v foobar  ; =>  (1 44 3 4 5)
于 2013-10-29T18:19:54.460 回答
0

利用setnth

(setq a (list 3 1 4 6 7))

(defun add-number-to-nth-element (arg liste element)
  "Add ARG, a number, to nth ELEMENT of LISTE. "
  (setnth element liste (+ arg (nth element liste)))
  liste)

(add-number-to-nth-element 5 a 1) 

;; ==> (3 6 4 6 7)
;; ==> (3 11 4 6 7)
;; ==> (3 16 4 6 7)
;; ==> (3 21 4 6 7)
;; ==> (3 26 4 6 7)

;; 计数元素从 0 开始

于 2013-10-24T09:58:13.480 回答