Dra. Jessica Andrea Carballido jac@cs.uns.edu.ar Dpto. de Ciencias e Ingeniería de la Computación UNIVERSIDAD NACIONAL DEL SUR Recursividad La recursividad es adecuada en problemas que reúnen las siguientes propiedades: • Existe al menos un caso trivial, que puede resolverse directamente. • Resolver cualquier instancia del problema - excepto el caso trivial - requiere resolver una o varias instancias más simples del mismo problema. Una instancia es más simple que otra si está más cerca del caso trivial. Recursividad Recursividad Ampliar a impares N CB: Si N tiene un dígito, ampliar a impares N es duplicar el dígito N si es impar, o es N si es par. CG: Si N > 9, ampliar a impares N es ampliar a impares N’ y agregarle al final el último dígito de N duplicado solo si el mismo es impar o agregar el último digito si es par. N’ es N sin su último dígito. Recursividad function Ampliar(N: integer): integer; begin if (N<=9) then if odd(N) then Ampliar:=N*10+N else Ampliar:=N else if odd(N mod 10) then Ampliar:=Ampliar(N div 10)*100+(N mod 10*10+N) else Ampliar:=Ampliar(N div 10)*10+N mod 10; end; Recursividad Reducir a pares N CB: Si N tiene un dígito, si el dígito es par, Reducir a pares N es N. Si es impar, reducir a pares N es 0. CG: Si N > 9, si el último dígito de N es impar, reducir a pares N es reducir a pares N’. Si es par, reducir a pares N es reducir a pares N’ y agregarle el último dígito de N al final. N’ es N sin su último dígito. Recursividad function Reducir(N: integer): integer; begin if (N<=9) then if odd(N) then Reducir:=0 else Reducir:=N else if odd(N mod 10) then Reducir:=Reducir(N div 10) else Reducir:=Reducir(N div 10)*10+N mod 10; end; Recursividad Codificar a letras N CB: Si N tiene un dígito, codificar a letras N es mostrar el dígito convertido a letra. CG: Si N > 9, codificar a letras N es codificar a letras N’ y mostrar luego el último dígito de N convertido a letra. N’ es N sin su último dígito. Para convertir a letra un dígito le sumamos 100 y buscamos el caracter ascii correspondiente a este número. Recursividad procedure codificar(N: integer); begin if (N <= 9) then write(chr(N+100)) else begin codificar(N div 10); write(chr(N mod 10+100)); end; end; Recursividad Recursividad Recursividad Problema: Leer por consola una secuencia de N números enteros y computar la suma de todos los números. Asuma N>=0. Suma de elementos de S con N elementos Caso trivial: Si N=0 (S es vacía), la suma de elementos de S es 0. Caso recursivo: Si N>0, la Suma de elementos de S es igual a la Suma de elementos de S’ + el primer elemento de S. Donde S’ es S sin su primer elemento. Recursividad function suma(n: integer): integer; var elem: integer; begin if (n = 0) Función then que respeta suma:= 0 el planteo else begin read(elem); suma:= suma(n-1)+elem; end; end; Traza Recursividad procedure sumaSecuencia(n: integer; var suma: integer); var elem, sumaSubsec: integer; begin if (n = 0) Procedimiento then que respeta suma:= 0 el planteo else begin Traza read(elem); sumaSecuencia(n-1, sumaSubsec); suma := sumaSubsec + elem; end; end; Recursividad program testSec; var n, suma: integer; procedure sumaSecuencia(n: integer; var s: integer); … begin … end; begin write ('Ingrese la cantidad de elementos de la secuencia: '); readln(n); sumaSecuencia(n, suma); writeln ('Suma = ', suma); end. Recursividad Problema: Calcular la suma de los números pares de una secuencia de números leída de consola. La secuencia está formada por números positivos y termina en 0, que no forma parte de la secuencia. Suma de pares de S Caso trivial: Si S es vacía, la Suma de pares de S es 0. Caso Recursivo: Si S no es vacía, y el 1er elemento de S es par, la Suma de pares de S es igual a la suma de pares de S’ + el 1er elemento de S. Caso Recursivo: Si S no es vacía, y el 1er elemento de S es impar, la Suma de pares de S es igual a la suma de pares de S’. Donde S’ es S sin su 1er elemento. Recursividad Implemente una función, consistente con el planteo recursivo, para calcular la suma de los números pares de S leída de consola. function sumaPares():integer; var n: integer; begin Con este “read” estamos read(n); achicando la instancia del if (n = 0) problema then sumaPares:=0 Al hacer cada llamada else recursiva, la secuencia if odd(n) tiene un elemento menos. then sumaPares := sumaPares() else sumaPares := sumaPares() + n; end; Recursividad Problema: Leer una secuencia de números de consola y calcular la suma de los números cuya suma de los dígitos pares es mayor a un cierto M. Por ejemplo si M=10 y la secuencia es 232 655 2803 2804 355 388 0 La salida del programa será 3192 (2804 +388) La secuencia está formada por números positivos y termina en 0, que no forma parte de la secuencia. • Dividir el problema en subproblemas. • Proponer un planteo recursivo para la resolución del problema principal y de cada subproblema. Recursividad Leer la secuencia de números enteros y sumar aquellos que cumplen con una determinada propiedad: la suma de sus dígitos pares es mayor a un cierto valor M. Supbroblema: - Calcular la suma de los dígitos pares de un número. El primer problema es análogo a uno de los problemas resueltos, sumar los números de una secuencia que cumplen una propiedad. El segundo problema (EL SUBPROBLEMA) está resuelto. Recursividad Leer la secuencia S de números enteros y sumar aquellos cuya suma de dígitos pares es mayor a un cierto valor M. S termina en 0. Suma elementos de S que cumplen con la propiedad Caso trivial: Si S es vacía, la Suma elementos de S que cumplen con la propiedad es 0. Caso Recursivo: Si S no es vacía, y el 1er elemento de S cumple con la propiedad, la Suma elementos de S que cumplen con la propiedad es igual a la Suma elementos de S’ que cumplen con la propiedad + el 1er elemento de S. Caso Recursivo: Si S no es vacía, y el 1er elemento de S NO cumple con la propiedad, la Suma elementos de S que cumplen con la propiedad es igual a la Suma elementos de S’ que cumplen con la propiedad. Donde S’ es S sin su 1er elemento. function sumaSec(M: integer): integer; Recursividad var n: integer; begin read(n); if (n = 0) then sumaSec:=0 else begin if (sumaDP(n) > M) then sumaSec:= sumaSec(M)+ n else sumaSec:=sumaSec(M); end; end; Se suman los elementos de una secuencia que cumplen con una propiedad. Recursividad program sumadeSumas; var suma, M: integer; function sumaDP(N: integer): integer; begin … end; function sumaSec(M: integer): integer; var N: integer; begin begin … write (‘Ingrese el valor de M’); end; readln(M); writeln (‘La suma es ‘, sumaSec(M)); end. Recursividad Recursividad Problema: Dada una secuencia S de N elementos (N>=0), determinar si en S aparece el elemento E. E Aparece en S? Caso trivial: Si S no tiene elementos, E no aparece en S. Caso recursivo: Si S tiene al menos un elemento, E aparece en S si el 1er elemento de S es igual a E, o si E aparece en S’. Donde S’ es S sin su 1er elemento. Recursividad N es la cantidad de elementos en la secuencia procedure estaEnSecuencia(E: integer; N: integer; var esta: boolean); var elem: integer; estaEnSprima: boolean; begin En “elem” se va if (N = 0) guardando cada then elemento de la secuencia esta:=FALSE else begin read(elem); estaEnSecuencia(E, N-1, estaEnSprima); Se podrá optimizar? esta:= (E=elem) OR estaEnSprima; end; end; Recursividad Problema: Dada una secuencia S de N elementos (N>=0), determinar si en S aparece el elemento E. Otro planteo… Aparece E en S? Caso trivial 1: Si N=0 (S es vacía), E no aparece en S. Caso trivial 2: Si N<>0, y E es igual al 1er elemento de S, E aparece en S. Caso recursivo: Si N>0, y el 1er elemento de S es distinto de E, E aparece en S si E aparece en S’. Donde S’ es S sin su 1er elemento. DOS casos triviales Recursividad function estaEnSecuencia(E: integer; N: integer): boolean; var elem: integer; begin if (N = 0) then Dos casos estaEnSecuencia:=FALSE triviales else begin read(elem); if (E=elem) then estaEnSecuencia:=TRUE else estaEnsecuencia:=estaEnSecuencia(E, N-1); end; end; Recursividad Problema: Leer por consola una secuencia de N números enteros y computar la suma de los pares y la suma de los impares. Asuma N entero no negativo. Suma pares y Suma impares de S Caso trivial: Si S está vacía, Suma pares es 0 y Suma impares es 0. Caso recursivo: Si S tiene al menos un elemento, y el 1er elemento de S es par, Suma pares de S es Suma pares de S’+ el 1er elemento de S. Suma impares de S es Suma impares de S’. Si el 1er elemento de S es impar, Suma impares de S es Suma impares de S’+ el 1er elemento de S. Suma pares de S es Suma pares de S’. Donde S’ es S sin su 1er elemento. procedure sumaSecuencia(n: integer; var spa, sim: integer); Recursividad var elem: integer; sumPsub, sumIsub: integer; begin if (n = 0) then begin spa:= 0; sim:= 0; end else begin read(elem); sumaSecuencia(n-1, sumPsub, sumIsub); if (odd(elem)) then begin sim := sumIsub + elem; spa:= sumPsub; end else begin sim:= sumIsub; spa := sumPsub + elem; end; end; end; Hacemos la traza Recursividad Problema: Dada una secuencia S de caracteres, que finaliza en punto, mostrarla invertida. Invertir S Caso Base: Si S es un punto, mostrar el punto. Caso Recursivo: Si S tiene más de un elemento, invertir S es invertir S’, y luego mostrar el primer elemento de S. Donde S’ es S sin su primer elemento. program invSec; Recursividad procedure invertirSecuencia; var ch: char; begin read(ch); if ch='.' then write(ch) else begin invertirSecuencia; write(ch); end; end; begin writeln('Ingrese la secuencia a invertir: '); invertirSecuencia; end. Recursividad Problema: Dada una secuencia S de caracteres (finalizada en punto), mostrar las vocales en el orden que aparecen, y luego las consonantes invertidas. Entre las vocales y las consonantes debe mostrar un asterisco. Los espacios no deben mostrarse. Recursividad Problema: Dada una secuencia S de caracteres (finalizada en punto), mostrar las vocales en el orden que aparecen, y luego las consonantes invertidas. Entre las vocales y las consonantes debe mostrar un asterisco. Mostrar vocales y consonantes de S Caso Base: Si S es un punto, mostrar un *. Caso Recursivo: Si S tiene más de un elemento; si el 1er elemento de S es una vocal, mostrarla y luego Mostrar vocales y consonantes de S’, si el 1er elemento de S es una consonante, Mostrar vocales y consonantes de S’ y luego mostrar la consonante, en otro caso Mostrar vocales y consonantes de S’. Donde S’ es S sin su primer elemento. procedure mostrarVyC; var ch: char; Recursividad begin read(ch); if ch='.‘ then write(' * ') else begin if esVocal(ch) then begin write(ch); mostrarVyC; end else if esLetra(ch) // es consonante ya que es letra y no es vocal then begin mostrarVyC; write(ch); end else mostrarVyC; end; end; Recursividad Asuma que cuenta con la función Propiedad que recibe un número y determina si cumple con una propiedad. propiedad: integer->boolean Escriba funciones o procedimientos para: Contar cuantos elementos en una secuencia de longitud N cumplen con la propiedad. Determinar si algún elemento en una secuencia de longitud N cumple con la propiedad. Determinar si todos los elementos de una secuencia de longitud N cumplen con la propiedad. Determinar si ninguno de los elementos de una secuencia de longitud N cumple con la propiedad. Recursividad Muestre la salida del siguiente procedimiento considerando n=8 y la siguiente secuencia ingresada por consola: bacaeddcaef procedure traza(n: integer); var x1, x2: char; begin if (n > 0) then begin read(x1); traza(n - 2); read(x2); writeln (x1, ’ ‘, x2) end end; Recursividad Problema 1: Dada una secuencia de enteros ingresada por teclado, mostrar sólo aquellos que son primos. La secuencia está formada por números positivos y termina en 0, que no forma parte de la secuencia. Problema 2: Leer una secuencia de números enteros y mostrar los solamente los que no tienen ningún dígito igual a 0 y que la suma de sus dígitos pares es mayor a cierto valor M. Recursividad Problema 3: Dada una secuencia de enteros ingresada por teclado de longitud L, con L par: tomar de a pares de elementos (primero con el segundo, tercero con el cuarto, etc.) y acumular sumando el mayor de cada par. Ej.: Para L=6 y la secuencia: 12 5 3 7 8 10 Se debe retornar: 12 + 7 + 10