Ejemplos de uso de las reglas de recursión A. PARA RECURSIÓN EN LISTAS SIMPLES (REGLAS 1 Y 2) Ejemplo 1: Escribir una función denominada “borrar” que admita con argumentos una lista y un elemento, y devuelva la lista original con la primera ocurrencia del elemento eliminada. ¿Condición de terminación?: 1) Lleguar al final de la lista sin encontrar el elemento a eliminar 2) Encontrar el elemento en la lista eliminarlo ¿Qué se hace con el first de la lista? Comprobar si es igual al buscado, y en su caso, eliminarlo Qué hacer con el rest? Aplicar recursión y comprobar si se ha llegado el final (defun borrar (lista elemento) (cond ((null lista) nil) ((equal (first lista) elemento) (rest lista)) (t (cons (first lista) (borrar (rest lista) elemento))))) Ejemplo 2: Escribir una función “longitud” que admita como argumento una lista y devuelva el recuento de todos los elemento del nivel más alto de la lista. (defun longitud (lista) (cond ((null lista) 0) (t (+ 1 (longitud (rest lista)))))) B. PARA RECURSIÓN CON LISTAS ANIDADAS Y EXPRESIONES (REGLA 3) Ejemplo 3: Escribir una función denominada “buscar ” que admita como argumentos una lista anidada y un átomo y devuelva ‘t si encuentra el átomo en la lista anidada y devuelva nil en otro caso. (defun buscar (lista elemento) (cond ((null lista) nil) ((atom (first lista)) (if (equal (first lista) elemento) 't (buscar (rest lista) elemento))) (t (or (buscar (first lista) elemento) (buscar (rest lista) elemento))))) (REGLA 4) Ejemplo 4: Escribir una función denominada “evalua ” que acepte como argumento una expresión en notación prefijo representada como una lista anidada y devuelva el valor numérico representado por la expresión. Solo pueden utilizarse como operadores: “+”, “-“ y “*”, y cada operador puede tener solo dos operandos. Por ejemplo: >(evalua ‘(* (+ 4 6) 4)) Deberá devolver: >40 (defun evalua (expr) (cond ((numberp expr) expr) ((equal (first expr) '+) (+ (evalua (second expr)) (evalua (third expr)))) ((equal (first expr) '-) (- (evalua (second expr)) (evalua (third expr)))) (t (* (evalua (second expr)) (evalua (third expr)))))) Ejemplos de uso de las reglas de recursión C. PARA RECURSIÓN EN NÚMEROS (REGLA 5) Ejemplo 5.a: Escribir una función denominada “suma-la-lista” que admita una lista de números y devuelva su suma. (defun suma-la-lista (lista) (cond ((null lista) 0) (t (+ (first lista) (suma-la-lista (rest lista)))))) Ejemplo 5.b: Escribir una función similar denominada “multiplica-la-lista”, que admita una lista de números y devuelva su producto. (defun multiplica-la-lista (lista) (cond ((null lista) 1) (t (* (first lista) (multiplica-la-lista (rest lista)))))) (REGLA 6) Ejemplo 6: El factorial de un número entero no negativo n es: N*(n-1)*(n-2)*...*3*2*1 Siendo además 1 el valor del factorial de 0. Implementar la función factorial en Lisp (defun factorial (n) (cond ((= n 0) 1) (t (* n (factorial (- n 1)))))) Ejemplo 7: Escribir una función denominada “resto ” que acepte dos números enteros positivos no nulos n y m y devuelva el resto cuando n resulta dividido por m. (defun resto (n m) (cond ((< n m) n) (t (resto (- n m) m)))) D. PARA TERMINACIÓN ADECUADA (REGLAS 7 Y 8) Ejemplo 8: Una función “exponente” toma dos enteros positivos no nulos x e y y eleva x a la potencia y ¿”exponente ” terminará adecuadamente? (defun exponente (x y) (cond ((= y 0) 1) (t (* x (exponente x (- y 1)))))) Si, de acuerdo con la regla 7, ya que se cumplen ambos principios: − Se cambia al menos un argumento en cada llamada recursiva Ejemplos de uso de las reglas de recursión − En el test de terminación (= y llamada recursiva (es decir, y ) 0) , se hace uso de un argumento que se cambia en la E. DE ABSTRACCIÓN (REGLA 9) Ejemplo 9: Escribir una función denominada “lista-al-cubo ” que acepta una lista de números y devuelve la misma lista con cada elemento reemplazado por su cubo. %%% Solución “ poco óptima”: (defun lista-al-cubo1 (lista) (cond ((null lista) nil) (t (cons (* (first lista) (first lista) (first lista)) (lista-al-cubo1 (rest lista)))))) %%% Solución “mejor”: (defun lista-al-cubo2 (lista) (cond ((null lista) nil) (t (let ((elemento (first lista))) (cons (* elemento elemento elemento) (lista-al-cubo2 (rest lista))))))) (REGLA 10) Ejemplo 10: Escribir una función denominada “cubo ” que admita un número y devuelva su cubo. Usar “cubo” para reescribir “lista-al-cubo”. (defun cubo (elt) (* elt elt elt)) (defun lista-al-cubo (lista) (cond ((null lista) nil) (t (cons (cubo (first lista)) (lista-al-cubo (rest lista)))))) (REGLA 11) Ejemplo 10: Sea una lista de dos números que representan un punto en el espacio euclídeo. Escribir una función denominada “obtener-lado” que acepte tres puntos: a, b, y c y un selector k. Los tres puntos representan los vértices de un triángulo. La función debe devolver un valor según los siguientes criterios: Si k=1, devuelve la longitud del lado a-b, si k=2, devuelve la del lado b-c y si k=3 devuelve la del lado c-a. En otro caso devuelve 0. (defun obtener-lado (a b c (cond ((= k 1) (sqrt (+ (exp (exp ((= k 2) (sqrt (+ (exp (exp ((= k 3) (sqrt (+ (exp (exp (t 0))) k) (- (first a) (first b)) 2) (- (second a) (second b)) 2)))) (- (first b) (first c)) 2) (- (second b) (second c)) 2)))) (- (first c) (first a)) 2) (- (second c) (second a)) 2)))) Ejemplos de uso de las reglas de recursión Ejemplo 11: Escribir una función denominada “distancia ” que acepte dos puntos (representados como listas de dos números) y devuelva la distancia euclídea entre ellos. Use “distancia” para reescribir “obtener-lado ”. (defun distancia (pt1 pt2) (sqrt (+ (exp (- (first pt1) (first pt2)) 2) (exp (- (second pt1) (second pt2)) 2)))) (defun obtener-lado (a b c k) (cond ((= k 1) (distancia a b)) ((= k 2) (distancia b c)) ((= k 3) (distancia c a)) (t 0)))