23 Recursion
23 Recursion
Funciones recursivas
Agenda
1 Introducción
2 Programación recursiva
Introducción I
Que nos miremos a nosotros mismos, que sólo contemos con nuestros
propios recursos para solucionar nuestros problema, que no se necesita
algo adicional. Que pensemos que lo podemos solucionar para que lo
solucionemos.
Agenda
1 Introducción
2 Programación recursiva
Recursividad I
Recursividad II
El mecanismo de la recursión
Recursividad III
Nota
En teorı́a una función no necesita tener casos base, pero cualquier función
recursiva escrita sin casos base generará un bucle infinito (ciclo sin fin).
Recursividad IV
Metodologı́a para resolver problemas recursivamente
Introducción
Problema 1.1
Problema
Calcular la suma de los números naturales desde el 0 hasta n.
Solución
Máximas dos y tres: El problema se puede solucionar si se pueden sumar
los números naturales desde el 0 hasta en n − 1 pues sólo
serı́a sumar ese número con el número n.
Máxima uno: Se supone que la función que suma los números naturales
desde el 0 hasta el n está bien por lo tanto se puede usar
para sumar los números naturales desde el 0 hasta el n − 1.
Máximas dos y tres: Sumar los números naturales desde el 0 hasta el 0 es
fácil, se debe retornar 0 pues es el primer número natural.
De esta manera será el último número en ser considerado en
la suma.
J. Gómez, A. Rodrı́guez, C. Cubides & C. Sierra Programación de Computadores – UN
Programación recursiva Recursión –9–
Introducción
Problema 1.2
Solución (continuación)
sumar : N → N
(
n + sumar (n − 1), si n > 0;
(n) 7→
0, en otro caso.
Introducción
Problema 2.1
Problema
Calcular la suma de los números almacenados en una lista.
Solución
Máximas dos y tres: Supongamos que la lista tiene n números. El
problema se puede solucionar si se pueden sumar los
primeros n − 1 números en la lista pues sólo serı́a sumar ese
número con el número que está en la posición n − 1.
Máxima uno: Se supone que la función que suma de los primeros n
números de una lista está bien por lo tanto se puede usar
para sumar los primeros n − 1 números en la lista.
Máximas dos y tres: Sumar los primeros 0 números de la lista es fácil, se
debe retornar 0 (no hay números que sumar).
Introducción
Problema 2.2
Solución (continuación)
sumar parcial : N∗ × N → N
(
Ln−1 + suma parcial(L, n − 1), si n > 0;
(L, n) 7→
0, en otro caso.
sumar lista : Nm → N
(L) 7→ sumar parcial L, m
Introducción
Problema 2.3
El programa quedarı́a:
def sumar_parcial(L,n):
if n > 0:
return L[n-1] + sumar_parcial(L,n-1)
else:
return 0
def sumar_lista(L):
return sumar_parcial(L,len(L))
Introducción
Problema 3.1
Problema
Determinar si un carácter está en una cadena.
Solución
Máximas dos y tres: Supongamos que la cadena tiene n caracteres. El
problema se puede solucionar si se puede determinar si un
carácter está entre los primeros n − 1 caracteres pues es mirar
si es el último o está entre los primeros n − 1 caracteres.
Máxima uno: Se supone que la función que determina si un carácter está
entre los primeros n está bien, por lo tanto se puede usar
para determinar si el carácter está entre los primeros n − 1
caracteres.
Máximas dos y tres: Determinar si está entre los primeros 0 caracteres de
la cadena es fácil, se debe retornar falso, ya que la cadena
vacı́a no contiene caracteres.
J. Gómez, A. Rodrı́guez, C. Cubides & C. Sierra Programación de Computadores – UN
Programación recursiva Recursión – 14 –
Introducción
Problema 3.2
Solución (continuación)
Introducción
Problema 3.3
El programa quedarı́a:
def buscar_parcial(str,ch,n):
if n > 0:
return (str[n-1] == ch) or buscar_parcial(str,ch,n-1)
else:
return False
def buscar(str,ch):
return buscar_parcial(str,ch,len(str))
Agenda
1 Introducción
2 Programación recursiva
Lectura y traducción I
Ejemplo
Sea f la función definida por:
f :N→B
V ,
si n = 0;
(n) 7→ F , si n = 1;
f (n − 2), en otro caso.
Lectura y traducción II
Ejemplo (continuación)
La traducción de la función f a Python es
def f(n):
if n == 0:
return True
elif n == 1:
return False
else:
return f(n-2)
Ejemplo
Sea g la función definida por:
g :N→N
0, si n = 0;
1, si n = 1;
(n) 7→
2, si n = 2;
g (n − 3), en otro caso.
Lectura y traducción IV
Ejemplo (continuación)
La traducción de la función g a Python es
def g(n):
if n == 0:
return 0
elif n == 1:
return 1
elif n == 2:
return 2
else:
return g(n-3)
Lectura y traducción V
Ejemplo
Sea h la función definida por:
h :N×N→N
(
n, si m = 0;
(n, m) 7→
h(n + 1, m − 1), en otro caso.
¿Cuál es el resultado de evaluar la función h con los valores
(n, m) = (2, 3), (8, 5), (6, 6)?
¿qué función matemática es h?
¿Cuál es su traducción a Python?
Lectura y traducción VI
Ejemplo
La traducción de la función h a Python es
def h(n,m):
if m == 0:
return n
else:
return h(n+1,m-1)
Problema
Problema
Diseñe un modelo matemático que permita calcular la función producto,
es decir, que reciba dos (2) números naturales y retorne la multiplicación
del primer número por el segundo.
Agenda
1 Introducción
2 Programación recursiva
Potencia de un número I
Ejemplo
En este ejemplo se definirá una función recursiva que permita hallar un
número real elevado a un número natural. Para expresar una función que
calcule esta operación, en primera instancia se construye la expresión
potencia : R × N → R que define la función que tiene como entrada un
número real que representa la base y un número natural que indica el
exponente, y como salida se obtendrá un número real que será la potencia.
Por facilidad, aquı́ se asumirá que 00 = 1.
Potencia de un número II
Ejemplo (continuación)
Ahora observesé que en general si se tiene una base b y un exponente n,
entonces por definición
bn = b
| ∗ b ∗ b ∗{z· · · ∗ b ∗ b}
n–veces
lo que es equivalente a
bn = b · · ∗ b ∗ b) ∗ b = b n−1 ∗ b
| ∗ b ∗ b ∗{z· · · ∗ b ∗ b} = |(b ∗ b ∗ ·{z }
n–veces n−1–veces
b := Base
n := Exponente
p := Potencia b n
entonces
potencia : R × N → R
(
1, si n = 0;
(b, n) 7→
potencia(b, n − 1) ∗ b, en otro caso.
Potencia de un número IV
Ejemplo
Suponga que se seleccionan cuatro cartas distintas de una baraja de póker,
que se van a representar por los sı́mbolos
¨ © ª «
si con estas cartas se conforma el conjunto cartas = ¨, ©, ª, « . ¿De
cuántas formas distintas se pueden organizar las cartas?.
Solución
Como se van a listar todas las formas posibles en que se pueden organizar
las cartas, el orden si importa.
Solución (continuación)
Una estrategia para encontrar el número de listas puede ser el siguiente:
1 Se selecciona una carta del conjunto cartas de forma arbitraria pero
fija, por ejemplo la carta ©.
2 Ya fijada la carta ©, el resto del trabajo consiste en hallar el número
de formas distintas de organizar
las
cartas restantes, es decir, el
conjunto cartas r {©} = ¨, ª, « .
3 Ahora por ejemplo se selecciona la carta « de forma arbitraria pero
fija.
4 A continuación, el trabajo se reduce a hallar el número de formas
distintas de organizar
las cartas restantes, es decir, el conjunto
cartas r {©, «} = ¨, ª .
Solución (continuación)
5 Posteriormente, por ejemplo se puede seleccionar de forma arbitraria
pero fija la carta ª.
6 Para finalizar, el trabajo se reduce a hallar el número de formas
distintas de organizarlas cartas restantes, es decir el conjunto
cartas r {©, «, ª} = ¨ . Como para este conjunto sólo se tiene una
opción, entonces el número de formas distintas de organizar un
conjunto de una carta es 1.
Siguiendo los pasos anteriores, se obtuvo la lista
© « ª ¨
Solución (continuación)
Del análisis previo se puede concluir que el número de formas de listar los
elementos de un conjunto con cuatro elementos se puede representar de la
siguiente manera
4 3 2 1
↓ ↓ ↓ ↓
Carta 1 Carta 2 Carta 3 Carta 4
Función factorial I
n! = n ∗ (n − 1) ∗ (n − 2) ∗ · · · ∗ 3 ∗ 2 ∗ 1 = n ∗ (n − 1)!
| {z }
n−1–veces
Función factorial II
fact(n) = f
entonces
fact : N → N
(
1, si n = 0;
(n) 7→
n ∗ fact(n − 1), en otro caso.
def fact(n):
if n == 0:
return 1
else:
return n * fact(n-1)
Ejemplo
Supónga que usted solicita un préstamo de $ 1’000.000 durante un año, el
prestamista cobra un interés del 5% mensual con la modalidad de interés
compuesto mes vencido. ¿Cuál es el total del dinero que debe pagar
cuando ha transcurrido el año por el cual solicitó el préstamo, resolviendo
el problema recursivamente?.
Solución
Para calcular el valor solicitado hay que observar que para cero (0) meses
hay que pagar
pago(0) = $10 000.000
Solución (continuación)
Para calcular la cantidad de dinero que hay que pagar al cabo de los 12
meses, es suficiente con tener en cuenta que en el mes 12 se debe pagar lo
que se debe en el mes 11 más los intereses que se producen en ese mes,
por ejemplo si pago(11) es el valor del pago en el mes 11, entonces la
cantidad de dinero que hay que pagar en el mes 12 es igual a
Solución (continuación)
ahora para calcular el valor a pagar en el mes 11 se puede hacer un
razonamiento similar, y para todos los meses anteriores hasta el mes
cero (0) se hace de manera similar, lo que genera un esquema recursivo
como el que se presenta a continuación
Solución (continuación)
Ası́, si m = $10 000.000, i = 0.05 y n = 12, se tiene que el pago al cabo de
los 12 meses será de pago(12) = $ 10 795.856, 326.
Solución (continuación)
pago(m, i, n) = valor
donde se tienen las variables
entonces
Solución (continuación)
pago : R+ × R+ × N → R+
(
m, n = 0;
(m, i, n) 7→
pago(m, i, n − 1) ∗ (1 + i), en otro caso.
Solución (continuación)
La codificación en Python de esta función es
Ejemplo
Una pareja de conejos recién nacidos (uno de cada sexo) se liberan en una
isla. Los conejos no pueden tener descendencia hasta que cumplen dos
meses. Una vez que cumplen dos meses, cada pareja de conejos tiene
como descendencia otra pareja de conejos cada mesa . ¿Cuál es la cantidad
de parejas de conejos en la isla una vez transcurrido un año, suponiendo
que ningún conejo muere?.
a
Este problema fué propuesto originalmente por el italiano Leonardo Pisano
Bigollo (1170–1250), más conocido como Leonardo de Pisa o Fibonacci (que
significa hijo de Bonacci, filius Bonacci) en su libro Liber abaci publicado en
1202.
Solución
Si fn denota la cantidad de parejas de conejos en el mes n, entonces, en el
mes cero, en éste aun no se ha hecho la liberación de la pareja de conejos,
por lo tanto la cantidad de parejas es f0 = 0.
n = 0, f0 = 0
n = 1, f1 = 1
Solución (continuación)
Durante el segundo mes, ya habı́a una pareja de conejos del mes anterior y
éstos aún no han alcanzado la edad para reproducirse, por lo tanto, no
hubo descendencia, de donde f2 es igual a la cantidad de conejos que
habı́an en el mes anterior más la descendencia que produjeron las parejas
de más de dos meses, es decir, f2 = 1.
n = 2, f2 = f1 + f0 = 1 + 0 = 1
Solución (continuación)
Durante el tercer mes, ya habı́a una pareja de conejos del mes anterior y
durante el transcurso de este mismo mes los conejos alcanzaron la
madures para reproducirse, por lo tanto hubo descendencia, de donde f3 es
igual a la cantidad de conejos del mes anterior más la descendencia que se
produjo en este mes, es decir, f3 = 2.
n = 3, f3 = f2 + f1 = 1 + 1 = 2 +
Solución (continuación)
Durante el cuarto mes ya habı́an dos parejas de conejos del mes anterior, y
la pareja madura es la que habı́a en el segundo mes, por lo tanto, la
descendencia fue generada sólo por esa pareja, de donde f4 es igual a la
cantidad de parejas del mes anterior más la descendencia que generé la
pareja del segundo mes, es decir, f4 = f3 + f2 = 2 + 1 = 3.
n = 4, f4 = f3 + f2 = 2 + 1 = 3 +
Solución (continuación)
Durante el quinto mes ya habı́an tres parejas de conejos del mes anterior, y
de éstas hay dos parejas maduras, que son las que habı́an en el tercer mes,
por lo tanto, la descendencia fue generada por esas dos parejas, de donde
f5 es igual a la cantidad de parejas del mes anterior más la descendencia
que generen las parejas del tercer mes, es decir, f5 = f4 + f3 = 3 + 2 = 5.
n = 5, f5 = f4 + f3 = 3 + 2 = 5 +
Solución (continuación)
Haciendo análisis similares se obtienen los siguientes resultados:
Solución (continuación)
De aquı́ que, transcurrido el primer año, en la isla habrán 144 parejas de
conejos.
A los números que son generados utilizando esta regla se les conoce como
números de Fibonacci.
A partir del análisis anterior, se puede diseñar una función recursiva que
permite calcular cualquier número de Fibonacci.
Solución (continuación)
fibo(n) = f
donde se tienen las variables
entonces
fibo : N → N
0,
si n = 0;
(n) 7→ 1, si n = 1;
fibo(n − 1) + fibo(n − 2), en otro caso.
Solución (continuación)
Una codificación en Python de esta función es
def fibo(n):
if n == 0:
return 0
elif n == 1:
return 1
return fibo(n - 1) + fibo(n - 2)
print(fibo(12))
Agenda
1 Introducción
2 Programación recursiva
Problemas III
Problemas
1 Modele mediante una función matemática y diseñe un programa
Problemas IV
Problemas
4 Modele mediante una función matemática y diseñe un programa
Problemas V
Problemas
6 Modele mediante una función matemática y diseñe un programa
Problemas VI
Problemas
9 Modele mediante una función matemática y diseñe un programa