为什么我的lisp函数返回'NIL'

时间:2017-02-11 22:24:19

标签: list lisp common-lisp clisp

我正在编写一个lisp函数,它将确定一个单词是不是使用'reverse'函数的回文结构。我对lisp相当新,我仍在努力掌握这个概念。每次测试回文时,函数都会返回NIL,任何想法为什么?

我想出了我的功能。

(defun palindromep (list)
    (cond
        ((null list)t)
        (t
            (and (equal (first list) (first (rest list)))
                (palindromep (butlast (rest list)))))))

代码修订

(defun palindromep (list)
    (cond
        ((null list)t)
        (t
            (and (equal (first list) (first(last list)))
                (palindromep (butlast(rest list)))))))

1 个答案:

答案 0 :(得分:1)

我怎么看它似乎工作了一组特殊的回文,其中有许多相同类型的元素。

您需要为一个元素列表返回t。即。 (null (cdr list))

如果第一个和第二个元素相同,则检查是否两个第一个元素相同。

修改

使用递归并且不使用我能想到的反向的最佳方法就是这样:

(defun palindromep (list)
  (labels ((aux (history tortoise hare)
             (cond ((null hare) (equal tortoise history))
                   ((null (cdr hare)) (equal (cdr tortoise) history))
                   (t (aux (cons (car tortoise) history)
                           (cdr tortoise)
                           (cddr hare))))))
    (aux '() list list)))

它的工作原理是通过额外的光标hare迭代两倍于tortoise的距离,同时看到的元素在history中累积。由于cons从头到尾创建列表,因此历史记录是反向所有看到的元素,因此当您到达中间时应该匹配结束。当野兔的cdrcddr为空时,您处于中间位置,可通过简单比较确定回文结构。

编辑2

如果您将帮助程序移出,则更容易跟踪并查看发生的情况:

(defun aux (history tortoise hare)
  (cond ((null hare) (equal tortoise history))
        ((null (cdr hare)) (equal (cdr tortoise) history))
        (t (aux (cons (car tortoise) history)
                (cdr tortoise)
                (cddr hare)))))

(defun palindromep (list)
  ;; just calls helper
  (aux '() list list))

;; trace the helper
(trace aux)
(trace equal) ; you might need to follow instructions to unlock

(palindromep '(1 2 3 3 2 1))
  0: (AUX NIL (1 2 3 3 2 1) (1 2 3 3 2 1))
    1: (AUX (1) (2 3 3 2 1) (3 3 2 1))
      2: (AUX (2 1) (3 3 2 1) (2 1))
        3: (AUX (3 2 1) (3 2 1) NIL)
          4: (EQUAL (3 2 1) (3 2 1))
          4: EQUAL returned T
        3: AUX returned T
      2: AUX returned T
    1: AUX returned T
  0: AUX returned T
==> T

(palindromep '(1 2 3 4 5 6))
  0: (AUX NIL (1 2 3 4 5 6) (1 2 3 4 5 6))
    1: (AUX (1) (2 3 4 5 6) (3 4 5 6))
      2: (AUX (2 1) (3 4 5 6) (5 6))
        3: (AUX (3 2 1) (4 5 6) NIL)
          4: (EQUAL (4 5 6) (3 2 1))
          4: EQUAL returned NIL
        3: AUX returned NIL
      2: AUX returned NIL
    1: AUX returned NIL
  0: AUX returned NIL
==> NIL