Title: Curso de Java
1LISP I
2Programación recursiva frente a iterativa
- Características de la programación recursiva
- Implementación intuitiva y elegante. La
traducción de la solución recursiva de un
problema (caso base y caso recursivo) a código
Lisp es prácticamente inmediata. - Útil para optimizar cálculos. Las estructuras de
datos en Lisp hacen un uso implíctito de los
punteros, como en las listas - NIL ó
- Un cons cuyo cdr es, a su vez, una lista
- Útil cuando hay varios niveles de anidamiento. La
solución para un nivel es válida para el resto. - Formas de hacer versión iterativa
- Con mapcar
- Con bucles (dolist, dotimes, etc. Desaconsejado).
3Ejemplos de recursividad, (1)
- Ejemplo del cálculo de la potencia de un número
optimizada - gt (defun potencia (x n)
- Optimizacion calculo potencia"
- (cond (( n 0) 1)
- ((evenp n) (expt (potencia x (/ n 2)) 2)
- )
- (t ( x (potencia x (- n 1))))))
- gt (potencia 2 3)
- 8
- La interpretación y comprensión del código es
compleja. Por ello es importante llegar a un
compromiso entre la claridad de la programación y
la eficiencia en la misma.
4Ejemplos de recursividad, (2)
- Contar los átomos de cualquier expresión LISP
- gt (cuenta-atomos '(a (b c) ((d e) f)))
- 6
- gt (defun cuenta-atomos (expr)
- (cond ((null expr) 0)
- ((atom expr) 1)
- (t ( (cuenta-atomos (first expr))
- (cuenta-atomos (rest expr))))))
5Ejemplos de recursividad, (3)
- Aplanar una lista
- (aplana (a (b c) ((d e) f))) gtgtgt
- (A B C D E F)
- gt (defun aplana (lista)
- (cond
- ((null lista) NIL)
- ((atom (first lista))
- (cons
- (first lista)
- (aplana (rest lista))))
- (t (append
- (aplana (first lista))
- (aplana (rest lista))))))
6Ejemplos de recursividad, (4)
- Número de sublistas de una lista (número de veces
que se abre paréntesis, menos 1) - (sublistas (a (b c) ((d e) f))) gtgtgt
- 3
- gt (defun sublistas (expresion)
- (cond ((or (null expresion) (atom
expresion)) - 0)
- (t ( (if (atom
(first expresion)) 0 1) -
(sublistas (first expresion)) -
(sublistas (rest expresion))))))
7Ejemplos de recursividad, (5)
- Producto escalar
- (producto '(2 3) '(4 5)) gtgtgt 23
- 2 x 4 3 x 5 23
- Versiones válidas
- Versión recursiva
- gt (defun producto (vector1 vector2)
- (if (or (null vector1) (null vector2))
- 0
- ( ( (first vector1) (first vector2))
- (producto (rest vector1) (rest
vector2))))) - Versión con mapcar
- gt(defun producto (vector1 vector2)
- (apply ' (mapcar ' vector1
vector2)))
8Ejemplos de recursividad, (6)
- Versión no válida del producto escalar
- Versión iterativa (no recomendable)
- gt (defun producto (vector1 vector2)
- (let ((suma 0))
- (dotimes (i (length vector1))
- (setf suma
- ( suma ( (nth i vector1)
- (nth i
vector2))))) - suma))
9Ejemplos de recursividad, (7)
- gt (defun profundidad-maxima (expresion)
- (cond ((null expresion) 0)
- ((atom expresion) 1)
- (t ( 1
- (apply 'max
- (mapcar
- 'profundidad-maxim
a - expresion))))))
- gtgtgt PROFUNDIDAD-MAXIMA
- gt (profundidad-maxima '(1))
- gtgtgtgt 2
- gt (profundidad-maxima '((1 (2 (3))) 4))
- gtgtgtgt 5
10Repaso de operadores, (1)
- Recordemos los siguientes operadores
- COUNT-IF, FIND-IF, REMOVE-IF, REMOVE-IF-NOT,
DELETE-IF, DELETE-IF-NOT - COUNT / COUNT-IF
- Contar apariciones
- (count ltelementogt ltlistagt
- test ltfun-igualdadgt)
- (count 2 (1 2 3 4 2 4 5 2))
- 3
- Contar los elementos que cumplen /no cumplen una
condición de una lista - (count-if-not ltpredicadogtltlistagt
- (count-if oddp (1 2 3 4 5 6))
- 3
11Repaso de operadores, (2)
- FIND / FIND-IF
- Devuelve la primera aparición
- (find ltelementogt ltlistagt
- test ltfun-igualdadgt)
- (find 2 (1 2 3 4 2 4 5 2))
- 2
- Devuelve el primer elemento que cumple/o no
cumple el predicado - (find-if-not ltpredicadogtltlistagt
- (find-if oddp '(1 2 3 4 2 4 5 2))
- 1
- REMOVE / REMOVE-IF
- Borrar las apariciones de un elemento indicado
- (remove ltelementogt ltlistagt
- test ltfun-igualdadgt)
- (remove 2 (1 2 3 4 2 4 5 2))
- (1 3 4 4 5)
- Elimina los que cumple/o no cumple el predicado
12Ejemplos de recursividad, (8)
- Objetivo sin utilizar remove-if, conseguir la
misma funcionalidad del operador - (quitar-si evenp '(1 2 3 4))
- (1 3)
- Versiones válidas
- Versión recursiva
- (defun quitar-si (predicado lista)
- (cond
- ((null lista) nil)
- ((funcall predicado (car lista))
- (quitar-si predicado (cdr lista)))
- (t (cons (car lista)
- (quitar-si predicado (cdr lista))))))
- Versión con mapcar
-
- (defun quitar-si (predicado lista)
- (delete
- NIL
13Ejemplos de recursividad, (9)
- Recorriendo la lista con dolist
- (defun QUITAR-SI (predicado lista)
- (let (listaaux)
- (dolist (i lista listaaux)
- (if (not (eval (list predicado i)))
- (setf listaaux (append listaaux (list
i))) - )
- )
- )
- )
14Ejemplos de recursividad, (10)
- Versión errónea
- Mal uso de mapcar. El hecho de que hagamos uso de
mapcar no garantiza la corrección del código
programado. - (defun QUITAR-SI2 (predicado lista)
- (mapcar
- (lambda (elemento)
- (if (apply predicado (list elemento))
- (remove elemento lista))
- )
- lista))
- gt (QUITAR-SI2 'evenp '(1 2 3 4))
- (NIL (1 3 4) NIL (1 2 3))