dificultades con el programa small lisp para palindrome

Hola a todos, estoy tratando de escribir una función lisp usando clisp v2.47 que toma una palabra y devuelve verdadero si es un palíndromo; de lo contrario, devolverá falso. Por cierto, lo que vale la pena mencionar es que soy nuevo en LISP, por lo que no tengo experiencia en escribir código LISP.

Aquí está mi código:

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

Cuando lo pego en clisp, está bien, pero cuando lo ejecuto, aparece este error que no sé cómo solucionar:

[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]>

Cualquier ayuda sería muy apreciada ya que tengo mucha prisa por terminar este programa.

Gracias a todos

preguntado el 03 de mayo de 12 a las 15:05

Es posible que desee ver la documentación para ÚLTIMO (particularmente los ejemplos). No creo que haga lo que crees que hace. -

4 Respuestas

La llamada (last ( L )) no calcula el último elemento de la lista L. Llama a la función llamada L sin ningún argumento, espera obtener una lista como valor devuelto y calcula el último células, de esa lista. (car (last L)) calculará el último elemento de una lista.

En Lisp, los paréntesis no son para agrupar sus declaraciones de código. En su lugar, significan una aplicación funcional.

(a b c d)

significa, "llamar a una función a con argumentos b, c, d".

(a)

significa, "llamar a una función a".

Entonces, su código no define ninguna función llamada L. Utiliza un parámetro llamado L, pero en Common LISP los nombres de funciones y los nombres de valores son dos espacios de nombres diferentes.

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

editar: Siguiendo la mejor idea de wvxvw, aquí hay un mejor código para ello, que no atraviesa tanto la lista:

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

contestado el 05 de mayo de 12 a las 00:05

Cualquier cosa que pongas en el primer elemento de una lista se trata como una función cuando se evalúa la lista. Intente eliminar algunos paréntesis sobrantes:

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

contestado el 03 de mayo de 12 a las 20:05

gracias por la ayuda, revisé mi código nuevamente e intenté eliminar la mayor cantidad de paréntesis posible y tuve el mismo problema. Sospeché que el problema está en la siguiente línea (palindrome (cdr (reverse (cdr L))))) así que eliminé ese caso y dejé los otros dos ((equal L '()) T ) y (T nil) y Recibí el mismo error nuevamente, así que es otra cosa, pero no puedo resolverlo: empollón

su cláusula NIL debería ser (NIL). Es lo que me dice mi CLISP. :) - Will Ness

te perdiste (y yo también, al principio) que (last L) regresa last células, de una lista, no la última elementos. - Will Ness

@nathan hughe, @will ness Hola, finalmente logré que el programa funcionara. El problema fue con la llamada a la función last, que devolvía una lista con el último elemento. Además de eso, había otro problema que es que cuando ingreso la entrada para ejecutar el programa, tengo que ingresarlo de la siguiente manera> palindrome ('(bob)) con espacios entre cada letra; de lo contrario, el resultado siempre es verdadero. Aquí hay un ejemplo para mostrarte lo que quiero decir > ​​palindrome('(bob) ) siempre es cierto. De todos modos, debo decir que en realidad fue bastante divertido resolver finalmente el problema y gracias a todos por su ayuda. - empollón

También (palindrome (coerce "redivider" 'list)) al usar cadenas - sbenitezb

Ese no es realmente un buen algoritmo que estás usando. Dará marcha atrás e irá al último elemento de la lista demasiadas veces (ambas reverse y last tienen velocidad O(n)). Llamará a reverse n/2 veces y last n/2 veces, haciendo que el tiempo de función general sea O (n ^ 2). A continuación se muestra un algo que hace lo mismo

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

pero en tiempo O(2n+n/2) como en el peor de los casos. Lo sé, no es muy "científico" poner una constante al lado de n aquí, pero es para ilustrar que si bien el tiempo es lineal, deberá visitar todos los nodos dos veces: la primera vez para calcular la longitud y la segunda vez para comparar liza. el n/2 es de llamar al revés antes de comparar.

Tenga en cuenta que hay una función de palíndromo ingenua muy sencilla:

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

Pero si estamos de acuerdo con mi O() anticientífico, entonces este es O(2n) (una vez que miramos toda la lista para invertirla, la segunda vez que miramos toda la lista para comparar resultados. Esta función realizará mejor que el primero en el peor de los casos, pero el primero funcionará mejor en el mejor de los casos. Además, no es raro que las implementaciones de Lisp almacenen la longitud de la lista en lugar de calcularla, lo que puede darte una reducción de casi la mitad de la velocidad en la primera función.

contestado el 04 de mayo de 12 a las 10:05

¡buena idea! (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))))) - Will Ness

He agregado esta versión basada en su idea a mi respuesta, con atribución a usted. Espero que esté bien. Sentí que sería una lástima dejarlo enterrado en los comentarios. debo retroceder? - Will Ness

(difunto palíndromo (L)

(condición

((igual L '()) T )

((igual (coche L) (coche(último L))) (palíndromo (cdr (reversa (cdr L)))))

(T CERO)

)

)

contestado el 04 de mayo de 12 a las 22:05

Hola a todos, lamento no haber publicado la respuesta final a mi pregunta porque soy nuevo en este sitio. Por lo tanto, de acuerdo con las regulaciones del sitio, un nuevo usuario no puede publicar una respuesta hasta después de 8 horas o algo así. El código anterior es el código final que funciona sin problemas: empollón

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.