tema 4: procedimientos y estructuras recursivas...ejercicio recursión mutua • implementa,...

33
Tema 4: Procedimientos y estructuras recursivas Sesión 10: Recursión (2) miércoles 9 de marzo de 2011

Upload: others

Post on 24-Aug-2020

27 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Tema 4: Procedimientos y estructuras recursivas

Sesión 10: Recursión (2)

miércoles 9 de marzo de 2011

Page 2: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Hoy veremos...

• Diseño de procedimiento recursivos

• Recursión mutua

• Coste espacial de la recursión

• Recursión por la cola

• Expresiones S

• Árboles binarios y genéricos

miércoles 9 de marzo de 2011

Page 3: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Recordamos... Recursión mutua

• Hay veces en que la definición matemática de una función se puede realizar en función de una segunda, que a su vez se define en base a la primera.

• Ejemplo:

• Programas en Scheme:

x es par si x-1 es imparx es impar si x-1 es par0 es par

(define (par? x) (if (= 0 x) #t (impar? (- x 1))))

(define (impar? x) (if (= 0 x) #f (par? (- x 1))))

miércoles 9 de marzo de 2011

Page 4: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Ejemplo avanzado de recursión mutua: Curvas de Hilbert

• Hilbert: matemático alemán que diseñó las curvas que llevan su nombre en 1900s.

• La curva de Hilbert es una curva fractal que tiene la propiedad de rellenar completamente el espacio. Su dibujo tiene una formulación recursiva.

• Vemos que la curva H3 se puede construir a partir de la curva H2.

H1 H2 H3

miércoles 9 de marzo de 2011

Page 5: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Ejemplo avanzado: curvas de Hilbert

• Utilizamos la librería graphics/turtles que permite usar la tortuga y comandos de Logo en Scheme (draw y turn).

• La función (h-der i w) dibuja una curva de Hilbert de orden i con una longitud de trazo w a la derecha de la tortuga.

• La función (h-izq i w) dibuja una curva de Hilbert de orden i con una longitud de trazo w a la izquierda de la tortuga.

miércoles 9 de marzo de 2011

Page 6: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Algoritmo curva de Hilbert

• Para dibujar una curva de Hilbert de orden i a la derecha de la tortuga:

• El algoritmo para dibujar a la izquierda es simétrico.

Gira la tortuga -90Dibuja una curva de orden i-1 a la izquierdaAvanza w dibujandoGira 90Dibuja una curva de orden i-1 a la derechaAvanza w dibujandoDibuja una curva de orden i-1 a la derechaGira 90Avanza w dibujandoDibuja una curva de orden i-1 a la izquierdaGira -90

miércoles 9 de marzo de 2011

Page 7: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Algoritmo en Scheme

(require graphics/turtles)(turtles #t)(define (h-der i w) (if (> i 0) (begin (turn -90) (h-izq (- i 1) w) (draw w) (turn 90) (h-der (- i 1) w) (draw w) (h-der (- i 1) w) (turn 90) (draw w) (h-izq (- i 1) w) (turn -90))))

(define (h-izq i w) (if (> i 0) (begin (turn 90) (h-der (- i 1) w) (draw w) (turn -90) (h-izq (- i 1) w) (draw w) (h-izq (- i 1) w) (turn -90) (draw w) (h-der (- i 1) w) (turn 90))))

miércoles 9 de marzo de 2011

Page 8: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Lo probamos

• Podemos probarlo con distintos parámetros de grado de curva y longitud de trazo:

• El resultado de esta última llamada es:

(clear)(h-izq 3 20)(h-izq 6 5)

miércoles 9 de marzo de 2011

Page 9: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Ejercicio recursión mutua

• Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas partes de la lista.

> (map-par cuadrado '(1 1 1 3 3 3)) (1 2 1 6 3 6)> (map-impar cuadrado '(1 1 1 3 3 3)) (2 1 2 3 6 3)> (map-par car '((1 2 3) (4 5 6) (7 8) (a b c))) ((1 2 3) 4 (7 8) a)> (map-impar car '((1 2 3) (4 5 6) (7 8) (a b c))) (1 (4 5 6) 7 (a b c))

– (map-par f lista): devuelve una nueva lista donde las posiciones pares son el resultado de aplicar f al correspondiente elemento en la lista, y las impares no varían.– (map-impar f lista): devuelve una nueva lista donde las posiciones impares son el resultado de aplicar f al correspondiente elemento de la lista, y las pares no varían.

miércoles 9 de marzo de 2011

Page 10: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Ejercicio recursión mutua

(define (map-par f lis) (if (null? lis) ‘() (cons (car lis) (map-impar f (cdr lis)))))

(define (map-impar f lis) (if (null? lis) ‘() (cons (f (car lis)) (map-par f (cdr lis)))))

>(map-par cuadrado (1 2 3 4))> (map-impar cuadrado (2 3 4))> >(map-par cuadrado (3 4))> > (map-impar cuadrado (4))> > >(map-par cuadrado ())< < <()< < (16)< <(3 16)< (4 3 16)<(1 4 3 16)

>(map-impar cuadrado (1 2 3 4))> (map-par cuadrado (2 3 4))> >(map-impar cuadrado (3 4))> > (map-par cuadrado (4))> > >(map-impar cuadrado ())< < <()< < (4)< <(9 4)< (2 9 4)<(1 2 9 4)

miércoles 9 de marzo de 2011

Page 11: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

La pila de la recursión

• Vamos a estudiar el comportamiento del proceso generado por una llamada a un procedimiento recursivo

• Examinamos cómo se realizan las llamadas recursivas

miércoles 9 de marzo de 2011

Page 12: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

La pila de la recursión

• Vamos a estudiar el comportamiento del proceso generado por una llamada a un procedimiento recursivo

• Examinamos cómo se realizan las llamadas recursivas

(define (mi-length items) (if (null? items) 0 (+ 1 (mi-length (cdr items)))))

miércoles 9 de marzo de 2011

Page 13: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

La pila de la recursión

• Vamos a estudiar el comportamiento del proceso generado por una llamada a un procedimiento recursivo

• Examinamos cómo se realizan las llamadas recursivas

(define (mi-length items) (if (null? items) 0 (+ 1 (mi-length (cdr items)))))

(mi-length '(a b c d))(+ 1 (mi-length '(b c d)))(+ 1 (+ 1 (mi-length '(c d))))(+ 1 (+ 1 (+ 1 (mi-length '(d)))))(+ 1 (+ 1 (+ 1 (+ 1 (mi-length '())))))(+ 1 (+ 1 (+ 1 (+ 1 0))))(+ 1 (+ 1 (+ 1 1)))(+ 1 (+ 1 2))(+ 1 3)4

miércoles 9 de marzo de 2011

Page 14: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

La pila de la recursión

• Cada llamada a la recursión deja una función en espera de ser evaluada cuando la recursión devuelva un valor (en el caso anterior el +)

• Esta función, junto con sus argumentos, se almacenan en la pila de la recursión

• Cuando la recursión devuelve un valor, los valores se recuperan de la pila, se realiza la llamada y se devuelve el valor a la anterior llamada en espera

• Si la recursión está mal hecha y nunca termina se genera un stack overflow

miércoles 9 de marzo de 2011

Page 15: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

El coste espacial de la recursión

• El coste espacial de un programa es una función que relaciona la memoria consumida por una llamada para resolver un problema con alguna variable que determina el tamaño del problema a resolver

• La notación O() indica una cota superior a ese coste

• En el caso de la función mi-length el tamaño del problema viene dado por la longitud de la lista

• El coste espacial de mi-length es O(n), siendo n la longitud de la lista

miércoles 9 de marzo de 2011

Page 16: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

El coste espacial depende del número de llamadas a la recursión

• Ejemplo: Fibonacci

• Secuencia de Fibonacci: 1,1,2,3,5,8,13

• Formulación matemática:

• En Scheme:

miércoles 9 de marzo de 2011

Page 17: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

El coste espacial depende del número de llamadas a la recursión

• Ejemplo: Fibonacci

• Secuencia de Fibonacci: 1,1,2,3,5,8,13

• Formulación matemática:

• En Scheme:

Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2) Fibonaci(1) = Fibonacci(0) = 1

miércoles 9 de marzo de 2011

Page 18: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

El coste espacial depende del número de llamadas a la recursión

• Ejemplo: Fibonacci

• Secuencia de Fibonacci: 1,1,2,3,5,8,13

• Formulación matemática:

• En Scheme:

Fibonacci(n) = Fibonacci(n-1) + Fibonacci(n-2) Fibonaci(1) = Fibonacci(0) = 1

(define (fib n) (cond ((= n 0) 1) ((= n 1) 1) (else (+ (fib (- n 1)) (fib (- n 2))))))

miércoles 9 de marzo de 2011

Page 19: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Evaluación de una llamada a Fibonacci

• Cada llamada a la recursión produce otras dos llamadas

• El número de llamadas finales es 2^n, siendo n el número que se pasa a la función

• Coste espacial y temporal: O(2^n)

• ¿Qué pasaría con (fibonaci 100)?

miércoles 9 de marzo de 2011

Page 20: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Proceso iterativo

• Es posible modificar la formulación de la recursión para se eviten las llamadas en espera

• Ejemplo: factorial iterativo

miércoles 9 de marzo de 2011

Page 21: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

• Secuencia de llamadas:

Factorial iterativo

(define (factorial-iter n) (fact-iter-aux n n))

(define (fact-iter-aux product n) (if (= n 1) product (fact-iter-aux (* product (- n 1)) (- n 1))))

(factorial-iter 4)(factorial-iter-aux 4 4)(factorial-iter-aux 12 3)(factorial-iter-aux 24 2)(factorial-iter-aux 24 1)24

miércoles 9 de marzo de 2011

Page 22: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

mi-length iterativo

• ¿Cómo sería la versión iterativa de mi-length?

miércoles 9 de marzo de 2011

Page 23: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

mi-length iterativo

• ¿Cómo sería la versión iterativa de mi-length?

(define (mi-length-iter lista) (mi-length-iter-aux lista 0))

(define (mi-length-iter-aux lista result) (if (null? lista) result (mi-length-iter-aux (cdr lista) (+ result 1))))

miércoles 9 de marzo de 2011

Page 24: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Procesos iterativos

• La recursión resultante es menos elegante

• Se necesita una parámetro adicional en el que se van acumulando los resultados parciales

• La última llamada a la recursión devuelve el valor acumulado

• El proceso resultante de la recursión es iterativo en el sentido de que no deja llamadas en espera ni incurre en coste espacial

miércoles 9 de marzo de 2011

Page 25: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Tail recursion

• A este tipo de recursión se le denomina tail recursion (definición en Wikipedia)

• Se puede realizar una implementación eficiente de la ejecución del proceso, eliminando la pila de la recursión

miércoles 9 de marzo de 2011

Page 26: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Fibonacci iterativo

• Cualquier programa recursivo se puede transformar en otro que genera un proceso iterativo

• En general, las versiones iterativas son menos intuitivas y más difíciles de entender y depurar

• Ejemplo: Fibonacci iterativo

miércoles 9 de marzo de 2011

Page 27: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Fibonacci iterativo

• Cualquier programa recursivo se puede transformar en otro que genera un proceso iterativo

• En general, las versiones iterativas son menos intuitivas y más difíciles de entender y depurar

• Ejemplo: Fibonacci iterativo

(define (fib-iter n) (fib-iter-aux 1 0 n))

(define (fib-iter-aux a b count) (if (= count 0) b (fib-iter-aux (+ a b) a (- count 1))))

miércoles 9 de marzo de 2011

Page 28: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Memoization

• Una alternativa que mantiene la elegancia de los procesos recursivos y la eficiencia de los iterativos es la memoization (enlace en la Wikipedia)

• Si miramos la traza de (fibonacci 4) podemos ver que el coste está producido por la repetición de llamadas; por ejemplo (fibonacci 3) se evalúa 2 veces

• En programación funcional la llamada a (fibonacci 3) siempre va a devolver el mismo valor

• Podemos guardar el valor devuelto por la primera llamada en alguna estructura (una lista de asociación, por ejemplo) y no volver a realizar la llamada a la recursión las siguientes veces

miércoles 9 de marzo de 2011

Page 29: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Triángulo de Pascal

• Formulación matemática:

11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 1 ...

miércoles 9 de marzo de 2011

Page 30: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Triángulo de Pascal

• Formulación matemática:

11 11 2 11 3 3 11 4 6 4 11 5 10 10 5 11 6 15 20 15 6 11 7 21 35 35 21 7 1 ...

Pascal (_,0) = Pascal (x,x) = 1 Pascal (fila, columna) = Pascal (fila-1,columna-1) + Pascal (fila-1, columna)

miércoles 9 de marzo de 2011

Page 31: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

• Formulación matemática:

• En Scheme:

Triángulo de Pascal. Versión recursiva

Pascal (_,0) = Pascal (x,x) = 1 Pascal (fila, columna) = Pascal (fila-1,columna-1) + Pascal (fila-1, columna)

miércoles 9 de marzo de 2011

Page 32: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

• Formulación matemática:

• En Scheme:

Triángulo de Pascal. Versión recursiva

(define (pascal row col) (cond ((= col 0) 1) ((= col row) 1) (else (+ (pascal (- row 1) (- col 1)) (pascal (- row 1) col) ))))

Pascal (_,0) = Pascal (x,x) = 1 Pascal (fila, columna) = Pascal (fila-1,columna-1) + Pascal (fila-1, columna)

miércoles 9 de marzo de 2011

Page 33: Tema 4: Procedimientos y estructuras recursivas...Ejercicio recursión mutua • Implementa, utilizando recursión mutua, una variante de map que sólo aplique la función a ciertas

Triángulo de Pascal. Versión iterativa

(define (pascal-iter fila col) (list-ref col (pascal-iter-aux '(1 1) fila)))

(define (pascal-iter-aux fila n) (if (= n (length fila)) fila (pascal-iter-aux (pascal-sig-fila fila) n)))

(define (pascal-sig-fila fila) (append '(1) (pascal-sig-fila-central fila) '(1)))

(define (pascal-sig-fila-central fila) (if (= 1 (length fila)) '() (append (list (+ (car fila) (car (cdr fila)))) (pascal-sig-fila-central (cdr fila)))))

miércoles 9 de marzo de 2011