小型lisp程序对回文的困难

时间:2012-05-03 14:59:59

标签: lisp clisp

大家好我试图使用clisp v2.47编写一个lisp函数,它接受一个单词并返回true如果它是一个回文,否则它将返回false。顺便说一句,值得一提的是,我是lisp的新手,因此我没有编写lisp代码的经验。

这是我的代码:

(defun palindrome( L )   
    (cond 
        ((equal L '()) T  )    
        ((equal (car (L)) (last ( L ))) 
            (palindrome (cdr (reverse (cdr (L))))))
        (t nil)))

当我将它粘贴到clisp中时它很好但是当我来运行时我得到了这个错误,我不知道如何修复:

[2]> (setq M '(bob))
(BOB)

[3]> (palindrome M)

*** - EVAL: undefined function L
The following restarts are available:
USE-VALUE      :R1      Input a value to be used instead of (FDEFINITION 'L).
RETRY          :R2      Retry
STORE-VALUE    :R3      Input a new value for (FDEFINITION 'L).
ABORT          :R4      Abort main loop
Break 1 [4]>

我非常感谢任何帮助,因为我真的急于完成这个计划。

全部谢谢

4 个答案:

答案 0 :(得分:4)

调用(last ( L ))不会计算列表L的最后一个元素。它调用名为L的函数,不带任何参数,期望获得一个列表作为返回值,并计算该列表的最后一个单元格(car (last L))将计算列表的最后一个元素。

在Lisp中,括号不用于对代码语句进行分组。它们代表功能应用。

(a b c d)

表示“使用参数a调用函数b, c, d”。

(a)

表示“调用函数a”。

因此,您的代码未定义任何名为L的函数。它使用名为L的参数,但在Common LISP中,函数名称和值名称是两个不同的名称空间。

[11]>
(defun palindrome( L )
    (cond
        ((null L) T  )
        ((equal (car L) (car (last L)))
            (palindrome (cdr (reverse (cdr L)))))))
PALINDROME
[12]> (palindrome '(bob))
T

编辑 按照 wvxvw 的最好的想法,这里有一个更好的代码,它不会如此遍历列表:

(defun palindrome (x) 
  (do ((x x (cdr x)) 
       (y x (cddr y)) 
       (z () (cons (car x) z)))
      ((null (cdr y)) 
       (equal z (if y (cdr x) x)))))

答案 1 :(得分:3)

无论您在列表的第一个元素中放置什么,都会在评估列表时将其视为函数。尝试删除一些多余的parens:

(defun palindrome( L )   
    (cond 
        ((equal L '()) T  ) 
        ((equal (car L) (last L)) 
            (palindrome (cdr (reverse (cdr L)))))
        nil))

答案 2 :(得分:1)

这不是你真正使用的好算法。您将反转并转到列表的最后一个元素太多次(reverselast都有O(n)速度)。您将反向调用n / 2次并持续n / 2次,使总功能时间为O(n ^ 2)。下面是一个做同样的算法

(defun palindrome-p (x)
  (let ((half-length (floor (/ (length x) 2))))
    (do ((i x (cdr x))
         (j 0 (1+ j)))
        (nil)
      (when (= j half-length)
        (labels ((compare (head tail)
                   (cond
                     ((or (null head) (null tail)) t)
                     ((not (equal (car head) (car tail))) nil)
                     (t (compare (cdr head) (cdr tail))))))
          (return (compare x (reverse i))))))))

但在O(2n + n / 2)时间内是最糟糕的情况。我知道,在这里放一个常数并不是非常“科学”,但它是为了说明虽然时间是线性的,但你需要两次访问所有节点 - 第一次计算长度和第二次比较名单。在比较之前,n / 2来自反向调用。

请注意,有一个非常直接的天真回文功能:

(defun naive-palindrome-p (x)
  (equal x (reverse x)))

但是如果我们同意我的反科学O(),那么这个是O(2n)(一旦我们浏览整个列表来反转它,我们第二次查看整个列表来比较结果。这在最糟糕的情况下,函数的性能会比第一个好,但是第一个函数在最好的情况下会表现得更好。而且,Lisp实现存储列表长度而不是计算它的情况并不少见,这可能会给你几乎一半第一个功能减速。

答案 3 :(得分:0)

(defun palindrome(L)

(cond

((等于L'())T)

((等于(车辆L)(车(最后L)))(回文(cdr(反向(cdr L)))))

(T NIL)