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

时间:2012-11-28 19:32:44

标签: lisp

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

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

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

示例:Position = 5,List =(1(2 3)((4))(5(6))),应返回(1(2 3)((4))((6)))。

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

(defun number_of_atoms(List)
 (atoms List 0)
)
(defun atoms(List Number)
 (cond
  ((null List) Number)
  ((atom (car List)) (atoms (cdr List) (+ 1 Number)))
  ((+ (atoms (car List) Number) (atoms (cdr List) 0)))
 )
)
(defun deleteElement(Pos List)
 (deleteElementAcc Pos 1 List)
)
(defun deleteElementAcc(Pos CurrPos List)
(cond 
  ((null List) nil)
  ((and (atom (car List)) (not(eql CurrPos Pos))) (cons (car List) (deleteElementAcc Pos (+ CurrPos 1) (cdr List))))
  ((and (atom (car List)) (eql CurrPos Pos)) (deleteElementAcc Pos (+ CurrPos 1) (cdr List)))
  ((cons (deleteElementAcc Pos CurrPos (car List))
         (deleteElementAcc Pos (+ CurrPos (number_of_atoms(car List))) (cdr List))))
)
)

2 个答案:

答案 0 :(得分:1)

为什么你把Pos和CurrPos的z拼写在一半的位置?

代码中的问题在于cond的最后一个分支。当您在List的cdr上递归时,CurrPos需要按照(car List)中的元素数量进行推进。而简单(长度列表)将无法工作,因为它需要递归计算子列表中的元素。

编辑:更详细说明 假设我们打电话

(deleteElement 3 '((1 2) (3 4)))  

你把它变成了

(deleteElementPos 3 1 '((1 2) (3 4))),

属于cond的最后一个案例,你得到了

(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))))

因为(汽车列表)中有2个元素。

所以,你只需要改变

(deleteElementAcc Pos CurrPos (cdr List))

(deleteElementAcc Pos (+ CurrPos (recursive-length (car List))) (cdr List))

和程序递归长度,这是一个非常简单的功能。它应该计算子列表中的元素,例如(recursive-length'((1 2)((3))))返回3.

答案 1 :(得分:0)

虽然以任何的方式解决这个问题并不是特别困难,但要解决它并不是一件容易的事。好吧,我指的是大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)))