Lisp 删除包含列表的列表中的元素

Lisp 删除包含列表的列表中的元素,lisp,Lisp,这里是LISP初学者。我正在为即将到来的LISP考试做准备,我遇到了一个无法解决的问题,所以我希望有更有经验的人能帮我解决 无论如何,我的问题是: 您将获得一个列表,其中可能包含列表作为元素。您的任务是删除给定位置的原子元素 列表和位置作为输入参数给出 示例:Position=5,List=(1(23)((4))(5(6)),应该返回(1(23)((4))((6))) 这是我到目前为止得到的…(PS下面的代码在imMaw的帮助下工作,您可以检查编辑以查看我以前的错误) 你为什么在一半的地方用z拼

这里是LISP初学者。我正在为即将到来的LISP考试做准备,我遇到了一个无法解决的问题,所以我希望有更有经验的人能帮我解决

无论如何,我的问题是: 您将获得一个列表,其中可能包含列表作为元素。您的任务是删除给定位置的原子元素

列表和位置作为输入参数给出

示例:Position=5,List=(1(23)((4))(5(6)),应该返回(1(23)((4))((6)))

这是我到目前为止得到的…(PS下面的代码在imMaw的帮助下工作,您可以检查编辑以查看我以前的错误)


你为什么在一半的地方用z拼写Pos和CurrPos

代码中的问题在于cond的最后一个分支。当您在列表的cdr上递归时,CurrPos需要按(car List)中的元素数前进。而一个简单的(长度列表)是行不通的,因为它需要递归地计算子列表中的元素

编辑:更多细节 说我们打电话

(deleteElement 3 '((1 2) (3 4)))  
你把这个变成

(deleteElementPos 3 1 '((1 2) (3 4))),
这属于最后一种情况,你得到

(cons (deleteElementAcc 3 1 '(1 2))
      (deleteElementAcc 3 1 '((3 4))))
请注意,currPos对于列表的cdr是错误的-它应该是3,而不是1。实际上,您希望您的代码变成

(cons (deleteElementAcc 3 1 '(1 2))
      (deleteElementAcc 3 (+ 1 2) '((3 4))))
因为(汽车列表)中有两个元素

所以,你只需要改变

(deleteElementAcc Pos CurrPos (cdr List))
进入


和程序递归长度,这是一个非常简单的函数。它应该计算子列表中的元素,例如(递归长度’((12)((3)))返回3。

为什么在一半的位置用z拼写Pos和CurrPos

代码中的问题在于cond的最后一个分支。当您在列表的cdr上递归时,CurrPos需要按(car List)中的元素数前进。而一个简单的(长度列表)是行不通的,因为它需要递归地计算子列表中的元素

编辑:更多细节 说我们打电话

(deleteElement 3 '((1 2) (3 4)))  
你把这个变成

(deleteElementPos 3 1 '((1 2) (3 4))),
这属于最后一种情况,你得到

(cons (deleteElementAcc 3 1 '(1 2))
      (deleteElementAcc 3 1 '((3 4))))
请注意,currPos对于列表的cdr是错误的-它应该是3,而不是1。实际上,您希望您的代码变成

(cons (deleteElementAcc 3 1 '(1 2))
      (deleteElementAcc 3 (+ 1 2) '((3 4))))
因为(汽车列表)中有两个元素

所以,你只需要改变

(deleteElementAcc Pos CurrPos (cdr List))
进入


和程序递归长度,这是一个非常简单的函数。它应该对子列表中的元素进行计数,例如(递归长度’((12)((3)))返回3。

虽然以任何方式解决这个问题都不是特别困难,但很好地解决它确实是非常重要的。我指的是大O和代码复杂度,以及角落案例的处理。我不确定这段代码是否能够处理甚至不正确的列表,而且它的某些部分肯定可以减少详细程度,但从技术上讲,它确实存在。它精确地以O(n)遍历树,其中n是树中的元素数,它使用O(n+2*(最大深度))空间,即它将使用树已经使用的内存,以及与树的最大深度成比例的内存

未尝试识别循环列表或重复列表:

(defun remove-from-tree-linear (tree &rest positions)
  (loop with node = tree
     with nilcar = (gensym)
     with positions = (sort (remove-duplicates positions) #'<)
     with counter = 0
     with copy = nil
     with root = nil
     with stack = nil
     with backrefs = nil
     while (or node stack) do
       (cond
         ((null node)
          (setf backrefs (cdr backrefs))
          (when (car stack)
            (setf copy (car backrefs)))
          (setf node (car stack) stack (cdr stack)))
         ((consp (car node))
          (if copy
              (if (eq (car copy) nilcar)
                  (setf (car copy) (list nilcar)
                        copy (car copy)
                        (car backrefs) copy)
                  (setf (cdr copy) (list nilcar)
                        copy (cdr copy)
                        (car backrefs) copy))
              (setf copy (list nilcar)
                    root copy))
          (setf backrefs (cons copy backrefs))
          (setf stack (cons (cdr node) stack)
                node (car node)))
         (t (if (and positions (= counter (car positions)))
                (setf positions (cdr positions))
                (if copy
                    (progn
                      (if (eq (car copy) nilcar)
                          (setf (car copy) (list (car node))
                                copy (car copy))
                          (setf (cdr copy) (list (car node))
                                copy (cdr copy)))
                      (setf (car backrefs) copy))
                    (setf copy (list (car node))
                          root copy
                          backrefs (list copy))))
            (setf node (cdr node))))
       (incf counter)
     finally (return root)))
(取消从树线性删除(树和静止位置)
(带节点的循环=树)
带nilcar=(gensym)

带位置=(排序(删除重复位置)#“虽然以任何方式解决这个问题都不是特别困难,但很好地解决它确实不是一件小事。我所说的好,是指大O和代码复杂性,以及处理角情况。我不确定这段代码是否能处理甚至不正确的列表,而且它的某些部分肯定可以减少冗长,但从技术上讲,它就在那里。它精确地以O(n)穿过树,其中n是树中元素的数量,它使用O(n+2*(最大深度))空间,也就是说,它将使用树已经使用的内存,以及与树的最大深度成比例的内存

未尝试识别循环列表或重复列表:

(defun remove-from-tree-linear (tree &rest positions)
  (loop with node = tree
     with nilcar = (gensym)
     with positions = (sort (remove-duplicates positions) #'<)
     with counter = 0
     with copy = nil
     with root = nil
     with stack = nil
     with backrefs = nil
     while (or node stack) do
       (cond
         ((null node)
          (setf backrefs (cdr backrefs))
          (when (car stack)
            (setf copy (car backrefs)))
          (setf node (car stack) stack (cdr stack)))
         ((consp (car node))
          (if copy
              (if (eq (car copy) nilcar)
                  (setf (car copy) (list nilcar)
                        copy (car copy)
                        (car backrefs) copy)
                  (setf (cdr copy) (list nilcar)
                        copy (cdr copy)
                        (car backrefs) copy))
              (setf copy (list nilcar)
                    root copy))
          (setf backrefs (cons copy backrefs))
          (setf stack (cons (cdr node) stack)
                node (car node)))
         (t (if (and positions (= counter (car positions)))
                (setf positions (cdr positions))
                (if copy
                    (progn
                      (if (eq (car copy) nilcar)
                          (setf (car copy) (list (car node))
                                copy (car copy))
                          (setf (cdr copy) (list (car node))
                                copy (cdr copy)))
                      (setf (car backrefs) copy))
                    (setf copy (list (car node))
                          root copy
                          backrefs (list copy))))
            (setf node (cdr node))))
       (incf counter)
     finally (return root)))
(取消从树线性删除(树和静止位置)
(带节点的循环=树)
带nilcar=(gensym)

带位置=(排序(删除重复位置)#'好的,问题是什么?@RainerJoswig我想知道如何解决我发布的问题。当然,但是你的代码在做什么或不做什么?好的,问题是什么?@RainerJoswig我想知道如何解决我发布的问题。当然,但是你的代码在做什么或不做什么?谢谢你的回答。我已经修复了z和s。你能帮我解决问题吗请写一段代码,帮助我跟踪真实的CurrPos?非常感谢。我知道问题是什么,但从未想过调用另一个函数来解决这个问题。:)干杯谢谢你的回复。我已经修复了z和s。你能写一个代码来帮助我跟踪真正的货币吗?非常感谢。我知道问题是什么,但从未想过调用另一个函数来解决这个问题。:)干杯