大家好我试图使用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]>
我非常感谢任何帮助,因为我真的急于完成这个计划。
全部谢谢
答案 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)
这不是你真正使用的好算法。您将反转并转到列表的最后一个元素太多次(reverse
和last
都有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)
)
)