回文小lisp程序的难点

回文小lisp程序的难点,lisp,clisp,Lisp,Clisp,大家好,我正在尝试使用clisp v2.47编写一个lisp函数,它接受一个单词,如果它是回文,则返回true,否则将返回false。顺便说一句,值得一提的是我是lisp新手,所以我没有编写lisp代码的经验 这是我的密码: (defun palindrome( L ) (cond ((equal L '()) T ) ((equal (car (L)) (last ( L ))) (palindrome (cd

大家好,我正在尝试使用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]>
任何帮助都将不胜感激,因为我真的很急于完成这个项目


感谢大家

在计算列表时,您在列表的第一个元素中输入的任何内容都会被视为函数。尝试删除一些多余的参数:

(defun palindrome( L )   
    (cond 
        ((equal L '()) T  ) 
        ((equal (car L) (last L)) 
            (palindrome (cdr (reverse (cdr L)))))
        nil))
调用
(last(L))
不会计算列表
L
的最后一个元素。它不带任何参数调用名为
L
的函数,期望得到一个列表作为返回值,并计算该列表的最后一个单元格<代码>(car(last L))将计算列表的最后一个元素

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

(a b c d)
表示“使用参数
b、c、d调用函数
a

表示“调用函数
a

因此,您的代码没有定义任何名为
L
的函数。它使用名为
L
的参数,但在常见的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)))))

你使用的算法不是很好。您将多次反转并转到列表的最后一个元素(
reverse
last
都具有O(n)速度)。您将调用reverse n/2次和last 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旁边加一个常数不是很“科学”,但这是为了说明,虽然时间是线性的,但您需要访问所有节点两次——第一次是为了计算长度,第二次是为了比较列表。n/2来自于在比较之前调用reverse

请注意,有一个非常简单的回文函数:

(defun naive-palindrome-p (x)
  (equal x (reverse x)))
但是如果我们同意我的反科学O(),那么这个就是O(2n)(一旦我们查看整个列表以反转它,第二次我们查看整个列表以比较结果。在最坏的情况下,此函数将比第一个函数执行得更好,但在最好的情况下,第一个函数将执行得更好。此外,Lisp实现存储列表长度而不是计算结果的情况并不少见这可能会在第一个函数中使速度降低一半。

(defun回文(L)

(续)

((等于L’())T)

((相等(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车)(左车

(无)

)


)

感谢您的帮助,我再次检查了我的代码,并尝试删除尽可能多的括号,但遇到了相同的问题。我怀疑问题出在下面的行(回文(cdr(reverse(cdr L‘‘‘‘‘‘‘‘‘‘‘‘‘‘‘)’),因此我删除了该行,并保留了另外两个((等于L’())T)和(T nil)我又犯了同样的错误,所以这是另外一个错误,但我无法理解你的从句NIL应该是(NIL)。这是我的CLISP告诉我的::)你没有(一开始我也没有)返回列表的最后一个单元格,而不是最后一个元素。@nathan hughe,@will ness嘿,我终于让程序运行了问题在于调用函数last,它返回一个包含最后一个元素的列表。除此之外,还有一个问题,那就是当我输入要运行程序的输入时,我必须按如下方式输入>回文('(bob)),每个字母之间有空格,否则结果总是正确的。这里有一个例子告诉你我的意思>回文('(bob))总是正确的。无论如何,我必须说,最终解决这个问题真的很有趣,感谢大家的帮助。还有
(回文(强制“redivider”列表))
使用Strings时,您可能需要查看文档(尤其是示例)。我不认为它能做你认为它能做的。大家好,很抱歉我没有发布我问题的最终答案,因为我是这个网站的新手。因此,根据网站规定,新用户在8小时或类似时间后才能发布答案。上面的代码是最终的代码,没有任何问题<代码>(defun回文(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())))
我根据你的想法在我的答案中添加了这个版本,并归因于你。希望没问题。我觉得把它埋在评论里太糟糕了。我应该后退吗?
(defun naive-palindrome-p (x)
  (equal x (reverse x)))