1. Quizás en la teoría cueste más ver lo que es una función recursiva que por la práctica. Un
ejemplo típico de recursividad sería la función factorial. El factorial es una función
matemática que se resuelve multiplicando ese número por todos los números naturales que
hay entre él y 1.
Por ejemplo, factorial de 4 es igual a 4 * 3 * 2 * 1. Si nos fijamos, para el ejemplo de
factorial de 4 (factorial se expresa matemáticamente con un signo de admiración hacia
abajo, como 4!), se puede resolver como 4 * 3! (4 * factorial de 3). Es decir, podemos
calcular el factorial de un número multiplicando ese número por factorial de ese número
menos 1.
n! = n * (n-1)!
En el caso de la función factorial, tenemos el caso básico que factorial de 1 es igual a 1. Así
que lo podremos utilizar como punto de ruptura de las llamadas recursivas.
Así pues, vamos a realizar la codificación de la función recursiva factorial. Primero veamos
un pseudocódigo:
funcion factorial(n)
si n=1 entonces
factorial = 1
sino
factorial = n * factorial(n-1)
fin funcion
unciones recursivas
Vamos a ver como se construye una clase de funciones, llamadas recursivas
primitivas, definidas entre n-uplas de números naturales sobre los números
naturales 31, (es decir ), con la idea de caracterizar las funciones
que son efectivamente calculables, es decir, aquellas funciones para las que
dada la n-upla de sus argumentos podemos definir un procedimiento para
encontrar en un numero finito de pasos el valor de la función.
Usaremos para ello una definición recursiva, es decir, nos apoyaremos en un
conjunto de funciones que por definición son recursivas (conjunto inicial que
se denomina base de la recursión), y en un conjunto de reglas que
aplicándolas a funciones recursivas primitivas ya definidas obtenemos nuevas
funciones recursivas. En nuestro caso la base esta formada por las
funciones nula, sucesor y proyección, y las reglas que llamamos
decomposición y de recursión primitiva. Estos elementos quedan definidos de
la siguiente forma:
Base de recursión:
Función nula :
2. mediante la que se hace corresponder a cualquier numero natural el
numero 0 (borrar el numero).
Función sucesor :
mediante la cual a cada numero natural se le hace corresponder su
sucesor, que denotamos por (encontrar el siguiente).
Función proyección :
mediante la cual a cada n-upla se le hace corresponder su i-esima
componente (elegir uno de una sucesión finita)
Reglas:
Regla de composición :
dadas las funciones
y la función que depende de las funciones anteriores, es decir
entonces decimos que
es la función compuesta de las mediante si está definida de la
siguiente forma:
Regla de recursion primitiva con parametros:
dadas dos funciones recursivas conocidas
3. que dependen de los parámetros , se define la función
mediante el siguiente esquema de recursión:
Regla de recursion primitiva sin parametros:
es un caso particular del anterior en el que no aparecerán los parámetros
y el esquema de recursión sería:
donde es una función recursiva conocida y es una constante
(un numero natural dado).
La clase de funciones definidas de esta manera, es una clase de funciones que
se puede calcular efectivamente, ya que son construidas a partir un conjunto
base, cuyo cálculo puede ser considerado trivial, y mediante procedimientos o
esquemas de cálculo sencillos y que se realizan por pasos sucesivos 32. Se
prueba que esta clase de funciones es la misma que la que se define utilizando
para ello las Maquinas de Turing, que describimos a continucion.
regunta 2
Escriba un programa que sirva para saber las posibilidades de movimiento de
un caballo en una partida de ajedréz de una casilla a otra (por ejemplo para
comer una pieza). Para ello se ha creado una matriz A[8][8] la cual contiene
un mapa del tablero (0 si la casilla está vacía o 1 si está ocupada) y se debe
crear un programa donde ingresando el punto de inicio y el de destino diga si
existe una combinación de movimientos posibles que lo lleven del inicio al
destino sin que pase a través de una casilla ocupada o no. (Problema
difícil!!!!,estudienlo)
4. Solución
/* 1 es SI HAY, 0 es NO HAY */
intrecorrer(int A[][], int i, int j, int p, int q)
{
if (i<0 || i>=8 || j<0 || j>=8) return false; /* Fuera del tablero */
if ((i==p) && (j==q)) return true; /* Mismolugar */
if (A[i][j]==1) return false; /* casilla ocupada */
A[i][j]=1; /* Ocupo la casilla */
/* Así evito ciclos */
return recorrer (A, i-2, j-1, p,q) ||
recorrer (A, i-2, j+1, p,q) ||
recorrer (A, i-1, j-2, p,q) ||
recorrer (A, i-1, j+2, p,q) ||
recorrer (A, i+1, j-2, p,q) ||
recorrer (A, i+1, j+2, p,q) ||
recorrer (A, i+2, j-1, p,q) ||
recorrer (A, i+2, j+1, p,q);
}
Pregunta 3
Un copo de nieve se puede definir como un punto, varias ramas en círculo que
salen de él y luego un copo de nieve de 1/3 del tamaño anterior en la punta de
cada una de esas ramas. Las ramas son del mismo tamaño y están dispuestas
con el mismo ángulo entre ellas. Se pide escribir una función recursiva:
5. dibuja_arbol(int x, int y, int n, int l, int nivel)
Donde (x,y) son las coordenadas del centro; n es el número de ramas; l es el
largo de las ramas y nivel es el número de niveles que quiero (en el último
nivel se dibuja un círculo de radio l). Por ejemplo, del llamado
dibuja_arbol(400,300,6,200,4) se obtiene:
Para calcular las ramas, deben encontrar el ángulo alfa y las coordenadas de
las puntas de todas las ramas, usando seno y coseno del ángulo
correspondiente. Para el caso de 8 ramas se tiene:
6. Para dibujar posee las funciones linea (int x1, int y1, int x2, int y2) que dibuja
una línea entre los puntos (x1,y1) y (x2,y2). Y el método circ (int x, int y, int
r) que dibuja una circunferencia de centro (x,y) y radio r.
Solución
#include<math.h>
voiddibuja_arbol(int x, int y, int n, int l, int nivel)
{
float alfa = 2*PI/n;
if(nivel == 0)
{
circ(x,y,l);
return;
}
/* Aca se itera con el angulo alfa */
for(int i = 0; i < n; i++)
{
linea(x, y, (int)(x+l*cos(i*alfa)), (int)(y-l*sin(i*alfa)));
dibuja_arbol((int)(x+l*cos(i*alfa)),(int)(y-l*Math.(i*alfa)),
n, l/3, nivel-1);
}
}
7. Problemas propuestos
Problema 1: Las torres de Hanoi
Se tienen las torres de Hanoi, en que hay que llevar las n fichas de A hasta C,
siempre dejando una ficha mas pequeña sobre otra mas grande. Se puede
utilizar B para pasar algunas fichas. Plantee el algoritmo recursivo que lo
realiza.
Problema 2: Tratamiento de enteros
Escriba una función recursiva que reciba un entero y retorne un String con los
digitos invertidos y separados por *. Por ejemplo:
Ingrese un número: 12345
5*4*3*2*1