LISP(将列表中间的值加一)

LISP (Add one to the value in the middle of the list)

我目前正在尝试创建一个函数,将列表中间的值加 1。

Example: (add1 '(2 4 6 5 9)) -> (2 4 7 5 9)

此外,如果列表是偶数,则 returns 没有。到目前为止,我有一个函数 returns 列表中间的位置。

(defun add1(aList)
               (if (oddp (length aList)) (- (/ (length aList) 2) .5) 'EvenNumber))

示例:(add1 '(2 4 6 5 9)) -> 2.0

有没有办法利用这些信息得到中间的值然后加1。谢谢

给你:

(defun add-1 (list)
  (let ((len (length list)))
    (assert (oddp len) (list))
    (incf (nth (/ (1- len) 2) list))))

如果您不想在偶数长度的列表上出现错误,请替换 assert with a when

尝试这样的事情。

(defun add1 (lst)
  (when (oddp (length lst))
    (incf (nth (floor (/ (length lst) 2)) lst)))
  lst)

我认为您需要的缺失部分是 setf(您可能已经使用过它,但也许您不知道可以使用 form第一个参数)或在本例中为 incf(增加一个或可选的指定增量)。它们允许您使用表达式来获取需要设置的值。

一些需要思考的事情(如所写):

  • 这是一个破坏性更新
  • 它在同一个列表上多次调用 length。这可能很昂贵。
  • 如我所写,偶数长度列表只是 return 列表不变。这不完全是您要求的,但也许是您想要的。
  • 我使用 floor 而不是乱用减法 .5,这将需要一些额外的转换。

这是一个函数,它只对列表进行两次传递而不是修改原始列表,并且不对整数执行任何算术运算:

(defun inc-middle-elt (list)
  (loop for elem in list
        for pair = list then (cddr pair)
        with flag = t
        when (and flag (null (cddr pair))) do
          (if (null (cdr pair))
            (incf elem))
          (setf flag nil)
        collect elem))

为了找到中间点,这使用了与链表的二进制合并排序实现中使用的技巧类似的技巧:辅助指针 pair 双步遍历列表,跨对。

(cddr pair)nil 时,我们处于最后一对。那时,必须做出决定:列表中的项目数是否为奇数?如果列表有奇数个项目,那么在最后一对位置,(cddr pair)nil,只剩下一个元素:(cdr pair) 也是 nil。

练习:利用链表中部之后的元素不需要复制的特点优化这个函数;输出列表可以共享输入列表的尾部。另外,更改函数,以便在清楚没有中间元素时,它 returns 原始列表。

我希望您正在寻找 递归版本,

(defun middle (lis)
 (let ((lis (c-in-place lis)))
  (cond ((null lis) nil) ((atom lis) lis)
   (t
    (mapcar
     #'(lambda (x)
        (cond ((atom x) x) (t (mapcar #'c-in-place (c-in-place x)))))
     lis)))))


(defun c-in-place (lis)
 (cond
  ((and (listp lis) (oddp (length lis)) (> (length lis) 2))
   (let ((pos (1+ (floor (/ (length lis) 2)))))
    (in-place (1+ (nth (floor (/ (length lis) 2)) lis)) pos lis)))
  (t lis)))

(defun in-place (nxt n lis)
 (let (temp temp1) (setf temp (subseq lis 0 (- n 1)))
  (setf temp1 (subseq lis n)) (setf temp (append temp (append `(,nxt) temp1)))
  temp))     

用法:

  1. (middle '((1 4 6 7 8) (3 4 2))) =>((1 4 7 7 8) (3 5 2))
  2. (middle '((1 4 6 7) (3 4 2))) => ((1 4 6 7) (3 5 2))
  3. (middle '(2 3 4)) => (2 4 4)
  4. (middle '(2 3 4 5) => (2 3 4 5)