Está en la página 1de 32

MP 11 Fundamentos Programacin

UF 02 Diseo Modular
MP 11 UF 02 Mdulo 4 Fundamentos Programacin. Pgina 1
MDULO 4 FUNDAMENTOS PROGRAMACIN EN C, C++.

OBJETIVOS.
Antes de ponernos en aspectos ms complicados y especficos del lenguaje C++,
aprovecharemos este mdulo para tratar dos temas muy diferentes entre ellos y que, en este
momento, nos permitir repasar todo lo que hemos aprendido en los mdulos anteriores.
El primero de estos temas es un tema puramente de tcnica de programacin: la
recursividad.
El segundo de los temas son los nmeros pseudoaleatorios, base de muchas simulaciones y
juegos, y un tema importante a la hora de proponer ejercicios interesantes de programacin.
Concretamente se revisarn los siguientes aspectos:
Recursividad:
Algoritmos recursivos frente a los algoritmos iterativos;
Tipos de recursividad: simple, mltiple, indirecta.
Nmeros pseudoaleatorios:
Concepto de nmero pseudoaletorio;
La funcin rand();
Formas de obtener nmeros pseudoaleatorios enteros y reales de diferentes rangos;
La funcin srand().
Es este, a mitad de curso, un buen momento para introducir una de las partes bsicas en el
desarrollo de aplicaciones: la depuracin. Esta no es propiamente una parte del lenguaje, aunque
est estrechamente ligado a este. El depurador es una herramienta externa al compilador. Se
incluye en este mdulo un anexo con una descripcin de las partes ms importantes de la
depuracin de aplicaciones de consola.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 2
1. RESUMEN TERICO.
1.1. LA RECURSIVIDAD.
Siempre se ha dicho que la palabra a definir no puede estar en la definicin. No obstante,
esta regla no es cierta en muchos lenguajes de programacin como el C/C++. Un lenguaje de
programacin se dice que es recursivo si una funcin (o subprograma) puede llamarse a s misma.
La recursividad es una tcnica de programacin elemental que permite que una funcin
pueda llamarse a s misma desde la misma funcin. Se puede utilizar la recursividad como una
alternativa a la iteracin (repeticin de un proceso dentro de un programa).
La recursividad es una herramienta poderosa e importante en la resolucin de problemas
en programacin. Una solucin recursiva es normalmente menos eficiente en trminos de tiempo
de computadora que una solucin iterativa debido a las operaciones auxiliares que llevan consigo
las llamadas suplementarias a las funciones; sin embargo, en muchas circunstancias el uso de la
recursin permite a los programadores especificar las soluciones naturales, ms lgicas,
elegantes, sencillas, que seran, en caso contrario difcil de resolver.
No todas las funciones pueden llamarse a s mismas, sino que deben estar diseadas
especialmente para que sean recursivas, de otro modo podran conducir a bucles infinitos, o a que
el programa termine inadecuadamente. Tampoco todos los lenguajes de programacin permiten
usar recursividad. C++ permite la recursividad.
Cada vez que se llama a una funcin, se crea un juego de variables locales, de este modo, si
la funcin hace una llamada a s misma, se guardan sus variables y parmetros, usando la pila, y la
nueva instancia de la funcin trabajar con su propia copia de las variables locales. Cuando esta
segunda instancia de la funcin retorna, recupera las variables y los parmetros de la pila y
contina la ejecucin en el punto en que haba sido llamada.
Un algoritmo recursivo es otra forma de hacer repeticiones sin utilizar estructuras iterativas
como while, dowhile o for.
Para que un algoritmo recursivo no se ejecute indefinidamente, es siempre necesario que
haya un caso (en general el ms simple) totalmente definido y que no necesita llamar de nuevo a
la funcin.
La mayor parte de los algoritmos recursivos admiten tambin una estructura iterativa.
Habitualmente, el cdigo iterativo es ms rpido que el cdigo recursivo, adems, si la llamada a
la funcin se realiza muchas veces, como cada vez el ordenador debe guardar espacio de memoria
para las variables de cada llamada, es fcil que se desborde esta memoria (la memoria destinada a
las variables locales y parmetros de la funcin se denomina pila).
Un ejemplo tpico de funcin que puede escribirse de forma recursiva es la funcin
factorial. Se define factorial de un nmero entero positivo n (anotaremos n!) como el producto de
todos los nmeros enteros positivos ms pequeos o igual a n; es decir: n!=n(n-1)(n-2)21. A
continuacin se presenta dos formas de implementar la funcin factorial, una iterativa con la
sentencia for y otra recursiva, la funcin recursiva se basa en el hecho que n!=n(n-1)!:
int factorial (int n){ //Versin iterativa.
int i=1, f=1;
for (i=1;i<=n;i++) f=f*i
return(f);
}

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 3
int factorial (int n){ //Versin recursiva.
int (n==0) return 1;
return(n*factorial(n-1));
}
El ejemplo anterior es un caso de recursividad simple; es decir, un caso en el cual en el
cuerpo de la funcin slo aparece una llamada a s misma. Una muestra de recursividad mltiple;
es decir, que en el cuerpo de la funcin aparecen ms de una llamada a s misma la tenemos en el
siguiente ejemplo que calcula el trmino ensimo de la sucesin de Fibonacci. Esta sucesin se
define de la siguiente forma:
a
1
=1 a
2
=2 a
n
=a
n-1
+a
n-2
si n>2
Los primeros valores de la sucesin de Fibonacci son: {1,2,3,5,8,13,21,}.
El cdigo para implementar esta sucesin es:
int fibon (int n){
if (n<=1) return 1;
return(fibon(n-1) + fibon(n-2));
}
Por ltimo, tambin se puede hacer una recursividad indirecta; es decir, que la funcin no
se llama directamente a s misma, sino que la funcin llama a una segunda funcin, y esta
segunda llama a la funcin inicial, por ejemplo, esta dos funciones se llaman la una a la otra;
ambas funciones retornan 1 si su argumento es el que indica el nombre de la funcin y 0 en otro
caso:
int par (int n){
if (n==0) return 1;
return impar(n-1);
}

int impar (int n){
if (n==0) return 0;
return par(n-1);
}
1.2. LOS NMEROS PSEUDOALEATORIOS.
Como casi todos los lenguajes de programacin, C incorpora en su librera estndar una
funcin que genera un nmero pseudoaleatorio. En el caso concreto de C, este nmero es un
entero comprendido entre 0 y 32.767. El prototipo de esta funcin es:
int rand()
y para utilizarla se debe incluir el fichero de cabecera stdlib.h.
Otros lenguajes de programacin incorporan tambin una funcin similar. Normalmente es
una funcin que genera un nmero real del intervalo [0, 1]. Esta funcin es ms til en muchos
casos.
Para generar en C un nmero real entre 0 y 1 (incluyendo el 0 y excluyendo el 1) podemos
utilizar la expresin:
(float) rand()/32768
Para generar un nmero real entre 0 y n [0, n] se utiliza la expresin:
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 4
(float) rand()*n/32768
De hecho, ambas expresiones generarn un nmero real de entre 32768 nmeros reales
comprendidos entre 0 y n, por tanto, no siguiendo estrictamente una distribucin uniforme.
Para generar un nmero entero entre 0 y n-1, ambos inclusive y n<32768, se utiliza la
expresin:
rand()*n/32768
Si n<32768, este mtodo har que haya nmeros que no se generarn, por ejemplo, si
n/32768=2, todos los nmeros generados sern pares. Este problema se puede solucionar
generando dos nmeros aleatorios, por ejemplo:
rand()*32768+rand()
es un nmero aleatorio comprendido entre 0 y 1.073.741.824.
El algoritmo interno que utiliza la funcin rand() utiliza un valor inicial para iniciar la
secuencia de nmeros aleatorios. La funcin srand() permite asignar un nuevo valor a este valor
inicial.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 5
2. ANEXO.
2.1. LA DEPURACIN.
Antes de producirse la versin definitiva de un programa debemos procurar que est libre
de errores. En el momento de la compilacin, este nos puede avisar de algunos errores de
sintaxis, confusin de tipos, etc. Estos errores que puede detectar el compilador se denominan
errores de compilacin y casi siempre son fciles de detectar.
Si para el compilador la sintaxis del programa es correcta, pero este no hace exactamente
lo que debera hacer, puede ser debido, seguramente, a un error lgico o error de ejecucin.
Estos tipos de errores son realmente difciles de detectar. Para ayudarnos a detectarlos se hace
imprescindible una herramienta que nos permita supervisar la ejecucin de nuestros programas y
acotar el error hasta la localizacin en el cdigo fuente. Utilizaremos el gdb bajo licencia GNU.
2.2. ERRORES Y ADVERTENCIAS DE COMPILACIN.
Una vez terminada la escritura del cdigo del programa se construye la aplicacin. Ya
hemos visto que todos los errores detectados por el compilador, as como otras advertencias, se
muestran en la ventana de salida, particularmente en la pestaa Build de esta ventana.
El compilador puede dar dos tipos de mensajes: los errores y las advertencias (warnings).
Las advertencias (warnings) son problemas leves o alertas sobre posibles problemas. Aunque el
compilador acabar creando el programa ejecutable es importante corregir estos errores que
originan las advertencias, porque seguro que sern el origen de futuros problemas ms graves.
Un error impide la construccin del ejecutable. El compilador nos informa del tipo de error
y la lnea en la que se produce el error. Hay que tener en cuenta que no todos los errores son
independientes, esto quiere decir que es probable que un mismo error produzca ms de un
mensaje de error, por ejemplo, si no declaramos una variable, el compilador detectar un error
cada vez que aparezca en el cdigo esta variable.
Los errores ms frecuentes que se suele cometer y que detecta el compilador son:
olvidar cerrar parntesis de funciones.
cambiar ( ) por [ ].
olvidar un punto y coma detrs de una instruccin.
olvidar cerrar las llaves de un bloque.
errores de sintaxis, por ejemplo escribir print ( ) en lugar de printf ( ).
utilizar funciones de biblioteca sin incluir los correspondientes ficheros de cabecera.
en las operaciones, olvidarse del smbolo de multiplicar, es decir, escribir 2x en lugar de
2 * x.
etc.
Adems de estos errores que obligan a corregir el cdigo y volver a compilar o construir la
aplicacin, el compilador nos avisa de algunas circunstancias que , aunque no impiden la
construccin de la aplicacin, pueden ser errores que se han corregir. Por ejemplo, el compilador
nos avisar si:
usamos una variable local antes de inicializarla.
hacemos conversiones automticas de tipos que pueden hacer perder informacin.
etc.
Si todo ha ido bien y el compilador ha hecho su tarea sin detectar ningn error, ya se puede
crear el ejecutable (F11).
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 6
2.3. EJEMPLO DE DEPURACIN CON EL TERMINAL.
Para que un programa pueda ser depurado correctamente, su ejecutable deber contener
cierta informacin que lo asocie al cdigo fuente del cual deriva. Para contener esta informacin
debemos compilar el programa con la opcin -g.
Alguna de estas funciones del depurador nos permitir hacer:
Ejecutar el programa lnea a lnea;
Poner puntos de parada en la ejecucin del programa (puntos de ruptura o
breakpoints).
Hay ciertos momentos que nos puede interesar el contenido de las variables.
Las rdenes para controlar la depuracin son las siguientes:
help Dar acceso al men de ayuda.
run Arranca la ejecucin del programa.
break Establece un punto de ruptura.
list Muestra las lneas del programa.
print Muestra el contenido de una variable.
next Ejecuta la siguiente lnea. Si esta es la llamada a una funcin la ejecuta
completamente.
step Ejecuta la siguiente lnea. Si se trata de una llamada a una funcin, slo ejecuta
la llamada y se detendr en la primera lnea de la funcin.
quit Termina la ejecucin del depurador.
Tomaremos la prctica 1 de este mdulo para probar el depurador. En las siguientes
capturas de pantalla podremos observar algunos de los comandos.
Primero debemos recordar compilar con la opcin -g gcc -g m4p01.c o m4p01. Llamamos al
depurador gdp m4p01 (nombre del ejecutable) y debemos tener una ventana abierta ms o
menos como la siguiente:


MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 7
Comprobaremos el comando list:

Comprobaremos las rdenes break, run y print:




MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 8
3. PRCTICA 1: LA SUMA DE LOS NATURALES.
En esta prctica confeccionaremos un programa para calcular la suma de los n primeros
nmeros de tres formas diferentes:
Realizando explcitamente las n-1 sumas.
Aplicando la frmula de la suma de los n primeros valores de una progresin aritmtica.
Mediante una algoritmo recursivo.
3.1. DESARROLLO DE LA PRCTICA.
La suma de los n primeros nmeros naturales se puede obtener mediante la frmula:


Por ejemplo, 1+2+3+4+5+6+7+8+9+10=10(1+10)/2=55
La suma de los n primeros nmeros naturales tambin puede hacerse mediante una
funcin recursiva, ya que: Sn=n+Sn-1. El problema de las funciones recursivas es que se puede
llenar la pila interna y el programa no funcionar bien para nmeros grandes.
En el programa que se presenta a continuacin se calcular la suma de los n primeros
nmeros enteros, siendo n un nmero entero entrado por teclado. Esta suma se har por los dos
mtodos antes mencionados y adems por un tercer mtodo que es un algoritmo iterativo muy
intuitivo.
Crearemos un nuevo archivo fuente C denominado m4p01.c y se escribir el siguiente
cdigo:
//m4p01.c - La suma de los n primeros nmeros naturales -

#include <stdio.h>
#include <stdlib.h>

int suma(int); //Prototipo de la funcin recursiva suma()

int main(){

int n, ct;
int suma1; //Hace el clculo con las n-1 sumas.
int suma2; //Aplica la frmula.
Int suma3; //Utiliza una funcin recursiva.

system("clear");

printf("Comprobacin de la frmula s=n(1+n)/2\n\n");
printf("Introduzca n: \n"); scanf("%d", &n);

suma1=0;

for (ct=1; ct<=n;ct++) suma1=suma1+cct;
suma2=n*(1+n)/2;
suma3=suma(n);
printf("Mtodo 1: 1+2++n: %d\n", suma1);
printf("Mtodo 2: (1+n)*n/2: %d\n", suma2);
printf("Mtodo 3: Recursivamente : %d\n", suma3);
return 0;

}
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 9
//Definicin de la funcin recursiva suma()
int suma(int n){
if (n>2) return n;
return n+suma(n-1);
}
3.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

3.3. EXPLICACIN DEL PROGRAMA.
La variable local suma1 almacenar el valor de la suma de los n nmeros de forma explcita
mediante el siguiente bucle:
suma1=0;

for (ct=1; ct<=n;ct++) suma1=suma1+cct;
Es importante inicializar el valor de la variable suma1 a 0 ya que las variables locales no se
inician a 0 automticamente.
La variable local suma2 almacena el valor de la suma a partir de la frmula antes
mencionada:
suma2=n*(1+n)/2;
Por ltimo, la variable suma3 almacenar el resultado de aplicar la funcin recursiva
suma(). Se denomina funcin recursiva porque en el cuerpo de la funcin hay una llamada a la
propia funcin:
//Definicin de la funcin recursiva suma()
int suma(int n){
if (n>2) return n;
return n+suma(n-1);
}
Toda funcin recursiva debe tener en cuenta un caso de escape; es decir, un caso en que
pueda salir de este bucle infinito que representa la recursividad. En esta funcin, en el caso que n
sea un valor ms pequeo que 2, retorna el mismo valor n y sale del bucle.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 10
4. PRCTICA 2: LAS TORRES DE HANOI.
Presentaremos en esta prctica el antiguo juego de las torres de Hanoi, uno de los ejemplos
clsicos de algoritmo recursivo.
4.1. DESARROLLO DE LA PRCTICA.
El juego parte de tres bases A, B y C. En estas bases se pueden poner discos, todos de
medida diferente, de forma que nunca puede estar un disco sobre otro que sea ms pequeo. Si
todos los discos estn inicialmente en la base A, el juego consiste en trasladarlos de uno en uno
hasta ponerlos en la base C, manteniendo siempre la regla que un disco nunca este sobre otro
que sea ms pequeo.

El siguiente programa implementa este proceso con la funcin recursiva Hanoi():
Crearemos un nuevo archivo C denominado m4p02.c y escribiremos el siguiente cdigo:
//m4p02.c - Torres de Hanoi -

#include <stdio.h>
#include <stdlib.h>

void Hanoi (int,char,char,char);

int main(){

int n;

system("clear");

printf("\t Introduzca el numero n de discos: ");
scanf("%d",&n);
Hanoi (n, 'A', 'C', 'B');
return 0;

}

void Hanoi (int n, char A, char C, char B){
if (n==1){
printf("%c->%c\t", A,C);
return ;
}
Hanoi (n-1, A, B, C);
Hanoi (1, A, C, B);
Hanoi (n-1, B, C, A);
}
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 11
4.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

4.3. EXPLICACIN DEL PROGRAMA.
Si hay slo un disco, el problema es trivial: es suficiente mover el nico disco de A hasta C.
denominaremos a este algoritmo Hanoi(1,A,C).

En el caso que haya dos discos, se puede hacer con tres movimientos: A->B, A->C, B->C; es
decir, tenemos un procedimiento para pasar dos discos de A en C utilizando B como ayuda.
Denominaremos a este algoritmo Hanoi(2,A,C,B) (pasar dos discos de A y C utilizando B.

En el caso que haya 3, se puede utilizar el algoritmo Hanoi(2,A,B,C); es decir, colocar dos
discos de A en B utilizando C como ayuda, Hanoi(1,A,C,B); es decir, colocar el disco de A en C y,
por ltimo, Hanoi(2,B,C,A); es decir, colocar los dos discos de B en C utilizando A como ayuda. A
todo este proceso lo llamaremos Hanoi(3,A,C,B).
En general, si hay n, se puede hacer Hanoi(n-1,A,B,C), Hanoi(1,A,C,B), Hanoi(n-1, B,C,A).
Esto es justamente lo que hace la funcin recursiva Hanoi():
void Hanoi (int n, char A, char C, char B){
if (n==1){
printf("%c->%c\t", A,C);
return ;
}
Hanoi (n-1, A, B, C);
Hanoi (1, A, C, B);
Hanoi (n-1, B, C, A);
}
En esta funcin, el caso de escape es el caso trivial n=1 en el cual se imprime el movimiento.
Si ejecutamos el programa con el valor 4 nos muestra los siguientes 15 movimientos:
A -> B A -> C B -> C A -> B C -> A C -> B A -> B A -> C B -> C
B -> A C -> A B -> C A -> B A -> C B -> C

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 12
5. PRCTICA 3: FRMULA DE WALLIS. OBTENCIN NMERO PI ().
Esta frmula del clculo avanzado permite tener una expresin muy sencilla para el nmero
. No obstante, se debe considerar un nmero considerable de trminos para que la
aproximacin sea buena. El inters de este programa no est tanto en el clculo del nmero
como el implante del algoritmo recursivo que permite este clculo.
5.1. DESARROLLO DE LA PRCTICA.
Una frmula interesante y que se puede deducir con herramientas avanzadas de clculo es
la frmula de Wallis, que permite tener una expresin del nmero a partir de estos productos:


A pesar de la sencillez de la frmula, no es sta una buena forma de aproximar el nmero ,
ya que esta serie de factores convergen muy lentamente, lo que equivale a decir que hacen falta
muchos factores para tener una aproximacin aceptable del nmero .
Abriremos un nuevo archivo denominado m4p03.c. Escribiremos el siguiente cdigo:
//m4p03.c - Frmula de Wallis -

#include <stdio.h>
#include <stdlib.h>

double wallis (int n);

int main(){
int n;
printf("Introducir el valor de n: \n");
scanf("%d",&n);
printf("pi = %lf\n",wallis(n));
return 0;
}

double wallis (int n){
if (n==1) return 4; //4=2*2
if (n%2) return double (n+1)/double(n)* wallis (n-1);
return double(n)/double(n+1)*wallis(n-1);
}
5.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 13
5.3. EXPLICACIN DEL PROGRAMA.
El clculo se hace con la funcin recursiva wallis(n), donde n indica el nmero de factores
que se consideran (sin contar el primer 2).
En el caso trivial, es decir, cuando n=1, tendremos wallis(1) = 4
wallis(2) = 2/3 * wallis(1) = 2/3*4
wallis(3) = 4/3 * wallis(2) = 4/3*2/3*4
En la definicin de esta funcin se puede comprobar que el clculo se hace de forma
diferente segn sea n un nmero impar o par. En el caso que n sea impar (n%2=1) hace:
wallis (n) = (n+1)/n * wallis(n-1)
y en el caso que n sea par (n%2=0) hace:
wallis (n) = n/(n+1) * wallis(n-1)
double wallis (int n){
if (n==1) return 4; //4=2*2
if (n%2) return double (n+1)/double(n)* wallis (n-1);
return double(n)/double(n+1)*wallis(n-1);
}


MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 14
6. PRCTICA 4: SACAR N CON M DADOS.
En esta prctica se resolver un interesante problema con una funcin recursiva: contar el
nmero de formas posibles en las que se puede obtener una puntuacin n con m dados.
6.1. DESARROLLO DE LA PRCTICA.
Si se juega con dos dados, sumando las puntuaciones obtenidas con ambos, cualquiera
puede observar que la puntuacin ms probable es la puntuacin 7.
Un jugador expres a Galileo su sorpresa cuando observ que al jugar con tres dados, la
suma 10 aparece con ms frecuencia que la suma 9. Segn este nmero, la suma 9 y 10 tienen los
mismos casos favorables:

Evidentemente, el jugador cometi un error al considerar casos igualmente favorables la
puntuacin 126 y la puntuacin 333, ya que la primera puede salir de 6 formas posibles: 126,
162, 216, 261, 612 y 621; y la segunda slo una forma posible.
Contando bien, teniendo en cuenta el orden, hay 27 casos favorables a la suma 10 y slo 25
casos favorables a la suma 9.
Este ejercicio nos da una idea sobre cmo hacer un programa con una funcin f(n,m) que
calcule el nmero de formas posibles de sacar una puntuacin n con m dados, considerando el
orden.
Para resolver el problema planteado, implementaremos una funcin recursiva f(n,m) que
har todo el clculo.
Crearemos un nuevo archivo C denominado m4p04.c y escribiremos en la ventana de
edicin el siguiente cdigo:
//m4p04.c - Obtener la puntuacin 'n' con 'm' dados -

#include <stdio.h>

int minimo (int, int);
int f(int, int);

int main(){

int n, m;

printf("\n Introducir el valor de 'n' (puntuacin)...");
scanf("%d",&n);

printf("\n Introducir el valor de 'm' (numero de dados)...");
scanf("%d",&m);

printf("\n El cantidad de formas de sacar la puntuacin %d con %d
dados es %d \n" ,n, m, f(n, m));
return 0;
}

int minimo (int a, int b){
return (a<b) ? a:b;
}
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 15
int f(int n, int m){

int ct,temp=0

if (m<1) return 0;
if (m==1){
if (n<1 || n>6) return0;
return 1;
}

for (ct=1; ct <= minimo(6, n-m+1); ct++){
temp = temp + f(n-ct, m-1);
}
return temp;
}
6.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

6.3. EXPLICACIN DEL PROGRAMA.
La funcin f() considera tres casos:
Si m<1, entonces retorna 0 ya que no se pueden tener 0 dados. Este caso slo se puede
dar en el caso que deliberadamente el usuario introduzca una cifra ms pequea que 1.
Si m=1 es el caso trivial en el que se sale de la recursividad. Con un dado slo se puede
obtener una puntuacin posible una sola vez.
En el caso que m>1, otorga al primer dado una puntuacin que est entre 1 y mnimo (6,
n-m+1) y, para cada una de estas puntuaciones posibles se cuenta el nmero de formas
como el resto de dados pueden formar la puntuacin que queda.
Ejemplo: Seguiremos el paso al clculo de f(9,3).
Si el primer dado es un 1, queda una puntuacin de 8 para los dos dados restantes;
es decir: f(8,2) formas.
Si el primer dado es un 2, queda una puntuacin de 7 para los dos dados restantes;
es decir, f(7,2) formas, y as sucesivamente. El nmero total ser:
f(9,3)=f(8,2)+f(7,2)+f(6,2)+f(5,2)+f(4,2)+f(3,2)+f(2,2)
A su vez, para sacar un 8 con dos dados, el primer dado puede ser un 2, un 3 o un 4.
La funcin considera tambin que puede comenzar por 1, pero f(7,1)=0:
f(8,2)=f(7,1)+f(6,1)+f(5,1)+f(4,1)=0+1+1+1=3
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 16
7. PRCTICA 5: SIMULACIN DEL CLSICO JUEGO DE LOS CHINOS.
Como primera prctica de simulacin de un juego se ha escogido este sencillo y tradicional
juego de los chinos. En esta prctica veremos diferentes casos de eleccin de nmeros aleatorios.
7.1. DESARROLLO DE LA PRCTICA.
En este juego, que en este caso se jugar con dos oponentes (el usuario y el ordenador),
cada uno de ellos debe pensar un nmero entero entre 0 y 3, haciendo una previsin de la suma
de las puntuaciones pensadas para los dos jugadores. Gana el jugador que acierte esta suma.
Crearemos un nuevo archivo denominado m4p05.c del tipo y escribiremos el siguiente
cdigo:
//m4p05.c - Juego de los chinos -

#include <stdio.h>
#include <stdlib.h>

void LimpiaBuffer() { while(getchar() != '\n'); }

int main(){
char c;
int jo,po; //Jugada y prevision del ordenador.
int jh,ph; //Jugada y prevision del humano.
int ct,i; //Contadores.
int punto=0,punth=0; //Marcadores de puntos.

for(ct=0;;ct++){
system("clear");
printf("Ordenador %d, humano %d\n", punto, punth);
printf("Jugada %d\n",ct);
printf("\n Introduzca su previsin...\n");

c=getc(stdin);if(c<'0'||c>'6') exit(1);ph=c-48;

//Escoge una jugada al azar.
jo=rand()%4; // Puede salir 0,1,2,3

if(ph==0) po=jo;
if(ph==1) po=jo+rand()% 2;
if(ph==2) po=jo+rand()% 3;
if(ph==3) po=jo+rand()% 4;
if(ph==4) po=jo+rand()% 3;
if(ph==5) po=jo+rand()% 2;
if(ph==6) po=jo+3;

printf("\n\n Ya he pensado mi jugada. ");
printf("\n Mi previsin es %d\n",po);
printf("\n Introduzca su jugada...");
LimpiaBuffer();
c=getc(stdin);if(c<'0'||c>'3') exit(1); jh=c-48;

printf("\n Mi jugada era %d",jo);
if(jh+jo==po) {
printf("\n Gana el ordenador\n");
punto++;
for(i=1;i<100000000;i++);
}else if(jh+jo==ph){
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 17

printf("\n Gana el usuario\n");
punth++;
for(i=1;i<100000000;i++);
}else {
printf("\n No hay ganador\n");
for(i=1;i<100000000;i++);
}
Limpiabuffer();
printf("\n Presione una tecla para continuar");
c=getc(stdin);

}
return 0;
}
7.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

7.3. EXPLICACIN DEL PROGRAMA.
En este programa se utilizan las variables jo y po para almacenar la jugada y la previsin que
hace el ordenador, y las variables jh y ph para almacenar la jugada y la previsin que hace el
usuario.
En esta versin del programa siempre comienza el usuario a hacer su previsin. La lectura
de este dato se hace en esta lnea de sentencias mltiples:
c=getche();if(c<'0'||c>'6') exit(1);ph=c-48;
Normalmente, se escribe una sentencia en una lnea diferente, pero en algunos casos
puede considerarse la posibilidad de agrupar diversos de diferentes en una misma lnea siempre
que sean cortas y que haga el cdigo ms claro. Como muchas cosas, esto depender del estilo o
del gusto de cada cual.
La jugada del ordenador se crea al azar con la siguiente sentencia:
jo=rand()%4; // Puede salir 0,1,2,3
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 18
La expresin de la derecha en la lnea anterior ser un nmero aleatorio entre 0 y 3.
C/C++ incorpora en su librera estndar esta funcin que calcula un nmero
pseudoaleatorio entre 0 y RAND_MAX (una constante simblica definida en el archivo de
cabecera <stdlib.h>. El valor de RAND_MAX ha de ser al menos 32767, el valor ms grande
positivo para un entero de dos bytes (16 bits). La funcin tiene el prototipo: ind rand(), y para
poder utilizarla se debe incluir el archivo de cabecera stdlib.h.
La previsin del ordenador no se hace realmente al azar sino dependiendo de los datos que
tiene: jo y ph. Podemos decir que la parte siguiente del cdigo es la parte "inteligente", la que
decide una u otra opcin segn la jugada del usuario:
if(ph==0) po=jo;
if(ph==1) po=jo+rand()% 2;
if(ph==2) po=jo+rand()% 3;
if(ph==3) po=jo+rand()% 4;
if(ph==4) po=jo+rand()% 3;
if(ph==5) po=jo+rand()% 2;
if(ph==6) po=jo+3;
Si la previsin del usuario es 0, el ordenador sabe que la jugada del usuario es 0 y, por tanto
decide que su previsin ser igual a su jugada.
Si la previsin del usuario es 1, el ordenador sabe que la jugada del usuario es 1 y, por tanto
decide que su previsin ser igual a su jugada ms un nmero aleatorio que puede ser 0 1.
..
Si la previsin del usuario es 5, el ordenador sabe que la jugada del usuario es 2 3 y, por
tanto decide que su previsin ser igual a su jugada ms un nmero aleatorio que puede ser 2 3.
Por ltimo, si la previsin del usuario es 6, el ordenador sabe que la jugada del usuario es 3
y, por tanto decide que su previsin ser igual a su jugada ms 3.
Una vez decidida la previsin se pide la jugada del humano para decidir quin ha ganado
aumentando en 1 el marcador correspondiente y volviendo de nuevo.
El programa acaba en el momento que se introduce una tecla errnea.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 19
8. PRCTICA 6: SIMULACIN DEL LANZAMIENTO DE DOS DADOS.
Uno de los usos ms didcticos de la programacin es la que nos permite entender el
concepto de probabilidad.
Sin entrar en definiciones formales, indicaremos que la idea intuitiva de probabilidad de un
acontecimiento es el lmite de la frecuencia relativa de este acontecimiento cuando el nmero de
realizaciones de la experiencia es muy grande.
La realizacin muchas veces de una experiencia es una tarea muy adecuada para un
programa informtico. En esta prctica simularemos el lanzamiento de dos dados muchas veces y
comprobaremos las probabilidades de todos los resultados posibles comparndolos con las
frecuencias relativas que se obtendr.
8.1. DESARROLLO DE LA PRCTICA.
Crearemos un nuevo archivo denominado m4p06.c y escribiremos el siguiente cdigo:
//m4p06.c - Simulacin de dos dados -

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int dado(void);

int main(){
int n=100000; //Nmero de simulaciones.
int ct;
int frecuencia[13]={0}; //Acumular las frecuencias.
int temp;

system("clear");
srand (unsigned) time (NULL));

for(ct=0;ct<n;ct++){
temp = dado() + dado();
frecuencia[temp]++;
}

for(ct=2;ct<=12;ct++){
printf("punt. %d, %d veces, frecuencia relativa: %.4f\n", ct,
frecuencia[ct], frecuencia[ct]*1.0/n) );
}
return 0;
}

int dado(){
return rand()%6+1;
}
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 20
8.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

8.3. EXPLICACIN DEL PROGRAMA.
Para poder generar un nmero pseudoaleatorio entero comprendido entre 1 y 6 se debe
utilizar la expresin: rand()*6 / 32768 + 1
Esta expresin se ha incluido dentro de una funcin denominada dado(). De esta forma
hacemos ms sencilla la comprensin del cdigo. Esta funcin no tiene argumentos que retorna
un nmero entero pseudoaletorio comprendido entre 1 y 16.
La lnea: temp = dado()+dado();simula el lanzamiento de dos dados y guarda su suma
en la variable temp. A continuacin se suma 1 a la variable frecuencia[temp]. Ya han salido en
prcticas anteriores variables indexadas como esta, en el mdulo 6 se tratar de forma ms
extensa el tema de las variables indexadas o vectores.
El algoritmo interno que utiliza la funcin rand() utiliza una semilla o valor inicial para iniciar
la secuencia de nmeros aleatorios. Para asegurarnos que cada vez que se ejecute el programa la
secuencia ser diferente se utiliza la siguiente lnea que asigna como valor inicial el nmero
entero retornado por la funcin time(), que corresponde a la hora en segundos del reloj interno
del ordenador; como las diferentes ejecuciones del programa se hacen en momentos diferentes,
este valor inicial ser diferente.
La funcin srand() es la que asigna este valor inicial: srand (unsigned) time
(NULL));
Para hacer la comprobacin sobre si la simulacin del lanzamiento de dos dados
corresponde a lo que se espera, el programa muestra las frecuencias absolutas y relativas de este
experimento. Se puede comprobar que en el caso en el cual n sea muy grande, las frecuencias
relativas corresponden a las probabilidades tericas.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 21
9. PRCTICA 7: GENERACIN DE NMEROS ALEATORIOS DE UN
INTERVALO.
En esta prctica utilizaremos los nmeros aleatorios para obtener nmeros enteros
aleatorios dentro de un intervalo.
9.1. DESARROLLO DE LA PRCTICA.
Se solicitar el lmite inferior y el superior del intervalo y se obtendrn 30 nmeros enteros
aleatorios incluidos los lmites.
Crearemos un nuevo archivo denominado m4p07.c y escribiremos el siguiente cdigo:
//m4p07.c - Generacin de nmeros aleatorios en un intervalo -

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){

int limite_inf, limite_sup, x, ct;

srand((unsigned)time(NULL));

system("clear");

printf("\n Introduzca el limite inferior del intervalo (entero): \n");
scanf("%d",&limite_inf);

printf("\n Introduzca el limite superior del intervalo (entero): \n");
scanf("%d",&limite_sup);

if (limite_inf>=limite sup)
printf("\n Error con los lmites. \n");
else
{
printf("\n Generacin de 30 numeros enteros aleatorios.\n");
for(ct=0; ct<30; ct++){
x=(int) (limite_inf + rand()%((limite_sup-limite_inf)+1));
printf("\t %d", x);
}
}
return 0;
}
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 22
9.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

9.3. EXPLICACIN DEL PROGRAMA.
Obtenemos los nmeros aleatorios mediante la sentencia:
x=(int) (limite_inf + rand()%((limite_sup-limite_inf)+1));
Pondremos 40 y 50 como lmites inferior y superior respectivamente. En la instruccin
rand()% (limite_sup - limite_inf) generamos aleatorios entre 0 y 10. El 10 no se incluye,
concretamente entre 0 y 9. A este dato le sumamos el lmite inferior (40) y como podremos
comprobar el 50 no saldr nunca. Es por este motivo que a la instruccin rand()%((limite_sup -
limite_inf)+1)) le sumamos 1.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 23
10. PRCTICA 8: ABSORCIN DE NEUTRONES.
La simulacin es una parte muy importante de muchas ramas de la ciencia. La fsica nuclear
es una de ellas. En esta prctica haremos una simulacin del comportamiento de los neutrones al
atravesar una pared de plomo en un reactor nuclear.
10.1. DESARROLLO DE LA PRCTICA.
La figura muestra un esquema muy simplificado de una seccin transversal de una pared
blindada de plomo de un reactor nuclear. Tambin muestra la trayectoria de dos neutrones que
han chocado contra esta pared.

Los neutrones entran en la pared y cada vez que se encuentran en una interseccin,
escogen al azar uno de los cuatro caminos posibles: volver atrs, avanzar, girar a la derecha o girar
a la izquierda.
Esta es la interpretacin que hacemos de una colisin entre un neutrn y un tomo de
plomo. Suponemos que la energa del neutrn le permite slo 10 colisiones con tomos de plomo,
tras los cuales el neutrn pierde totalmente su energa cintica y se detiene.
En el dibujo, el neutrn de la izquierda no ha podido atravesar la pared y si ha podido el
neutrn de la derecha. Realizaremos una simulacin que nos pueda decir qu porcentaje de
neutrones atravesar la pared en funcin del grueso de la pared de plomo. Tambin nos interesa
el porcentaje de neutrones que son reflejados hacia atrs.
Denominaremos n al grueso de la pared, es decir, el nmero de capas de tomos de plomo
(en el dibujo n=4). Cada una de las capas se denominar 0, 1, , n-1. El neutrn comienza siempre
chocando con un tomo de la capa 0. En este momento escoge un nmero entero al azar entre 0
y 3: 0 es hacia atrs, 1 hacia la izquierda, 2 hacia la derecha y 3 hacia adelante.
Un neutrn ha atravesado la pared si ha llegado a la capa n antes de 10 choques y se ha
reflejado si llega a la capa n-1 antes de 10 choques.
Crearemos un nuevo archivo denominado m4p08.c y escribiremos el siguiente cdigo:
//m4p08.c - Absorcin de neutrones -

#define N_NEUTRONES 100000

#include <stdio.h>
#include <stdlib.h>

int main(){

int n=4; //Nmero de capas de la pared de plomo.
int energa=10; //Energa cintica inicial de los neutrones medida en
nmero de choques mximos.
int dado; //Nmero aleatorio entre 0 y 3.
int capa; //Nivel actual del neutrn.
int trav=0; //Nmero de neutrones que atraviesan.
int ref=0; //Nmero de neutrones que son reflejados.
int abs=0; //Nmero de neutrones que son absorbidos.
int neutrones = N_NEUTRONES; //Nmero de neutrones.
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 24
system("clear");

while (neutrones--){
capa=0;
energa=10;
while (energa--){
dado = rand()%4
switch (dado){
case 0:
capa--;
break;
case 3:
capa++;
break;
}
if (capa==n){
trav++;
break;
}
if (capa==n){
ref++;
break;
}
}
}
abs = N_NEUTRONES - trav - ref;

printf("\n %d Neutrones en total.\n", N_NEUTRONES);
printf("\n Han pasado %d neutrones %f%%\n", trav, (float)
(trav)*100/N_NEUTRONES);
printf("\n Han rebotado %d neutrones, %f%%\n", ref, (float)
(ref)*100/N_NEUTRONES);
printf("\n sido absorbidos %d neutrones, %f%%\n", abs, (float)
(abs)*100/N_NEUTRONES);

return 0;
}

10.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.


MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 25
10.3. EXPLICACIN DEL PROGRAMA.
En este programa, se simula la trayectoria de N_NEUTRONES pasando por la pared de plomo.
El bucle principal comienza con: while (neutrones--){, donde la variable neutrones
comienza con N_NEUTRONES y va disminuyendo en una unidad cada vez que se ejecuta el bucle.
En el momento en el cual neutrones sea 0, la condicin ser falsa y se saldr del bucle.
Por cada neutrn se inicializa su estado (posicin: capa=0 y energa=10). El bucle de
choques de cada electrn se ejecuta hasta que la energa sea =. En cada choque, esta energa
disminuye en una unidad.
A la variable dado se le asigna un nmero aleatorio entre 0 y 3 y, segn este valor, cambia
la posicin del neutrn. Esto es lo que hace la sentencia switch. Despus de esta sentencia, dos
sentencias if comprueban si el neutrn ha atravesado la pared o ha rebotado.
Por ltimo, se muestra por pantalla el resultado d esta simulacin. Se muestra el nmero
total y el porcentaje de neutrones que atraviesan, los que son reflejados y los que son absorbidos
por la pared.
En esta simulacin se ha optado por asignar directamente los valores del programa, pero
tambin se puede solicitar entrara estos datos y hacer el programa ms general.
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 26
11. PRCTICA DE AMPLIACIN: LAS OCHO REINAS.
Este es uno de los problemas ms utilizados para mostrar una tcnica de programacin que
se denomina algoritmos de vuelta atrs o, en ingls, backtracking.
11.1. DESARROLLO DE LA PRCTICA.
El problema de las ocho reinas consiste en colocar en un tablero de ajedrez (que tiene
8x8=64 casillas) ocho reinas de forma que ninguna de ellas amenace a ninguna otra.
Un mtodo de encontrar todas las posiciones posibles de colocar 8 reinas en un tablero de
ajedrez y probar una a una si se cumple la condicin es un mtodo muy poco eficiente ya que hay
4.426.165.368 de posibilidades. Se podra mejorar si asignamos a cada una de las reinas una
columna del tablero y slo nos preocuparemos de escoger una fila para cada una de las reinas. El
nmero de posibilidades ha bajado a 8
8
=16.777.216.
Si una vez colocada la reina de la columna 1 en la fila 4, por ejemplo, prohibiremos que la
fila 4 vuelva a salir, slo tenemos 7 posibilidades para la segunda reina. Si prohibimos que la
tercera reina est en la misma fila que la primera o que la segunda, tenemos 6 posibilidades para
la tercera reina; es decir, slo deberemos probar 8!=87654321=40.320.
El mtodo de vuelta atrs consiste en explorar soluciones parciales y aceptarlas o
rechazarlas. Una solucin parcial es rechazada si ella misma no cumple las condiciones que se
imponen a una solucin o bien ninguna de las soluciones que se pueden formar a partir de ella las
cumple. En el caso del problema de las ocho reinas se actuar de la siguiente forma:
1 - Seleccionamos una casilla para la reina 1, (en este caso todas son posibles en principio).
2 - Seleccionamos una casilla para la reina 2, si no hay casillas disponibles, volver al punto 1.
3 - Se comprueba si la pareja Reina1-Reina2 es posible, en caso contrario volver al punto 2.
4 - Seleccionamos una casilla para la Reina3.
5 -

En la parte izquierda del diagrama se muestra un ejemplo de exploracin siguiendo el
proceso de vuelta atrs por el problema de las cuatro reinas, un problema reducido, pero que nos
servir para comprender bien el proceso: en primer lugar, asigna a la primera reina la fila 1.
En segundo lugar, asigna a la segunda reina la fila 1, como las dos reinas se amenazan, esta
posicin no es buena y se rechaza y, por tanto, no sigue la exploracin para esta rama del rbol.
Se asigna a la segunda reina la fila 2 y se rechaza tambin.
Se asigna a la segunda reina la fila 3 y, como no hay amenaza se sigue explorando esta
rama. Se comprueban todas las posiciones de la tercera reina y ninguna de ellas cumple la
situacin, por tanto, se rechaza tambin la solucin parcial 1-3.
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 27
Este procedimiento se sigue hasta encontrar la primera solucin que, como puede verse en
la parte central del diagrama anterior, es la 2, 4, 1, 3 y corresponde a la siguiente situacin
representada en la parte derecha del diagrama anterior.
La primera solucin encontrada en el caso de las ocho reinas es: 1 5 8 6 3 7 2 4 que
corresponde al siguiente diagrama situado a la derecha:
El cdigo para resolver este problema es el siguiente:
//m4pa1.c - El problema de la n reinas -

#include <stdio.h>
#include <stdlib.h>
#define NUM_REINAS 8

void Explorar(int*,int, int);
int Comprueba(int*, int );

int main(){
int sol[NUM_REINAS]; //Vector solucin.
system("clear");
Explorar(sol,0,0);
return 0;
}
void Explorar(int *sol, int n, int ct){
do{
sol[n]=ct;
if (Comprueba(sol, n)){
if (n==NUM_REINAS-1){
printf("FIN\n");
for(ct=0;ct<NUM_REINAS;ct++){
printf("%d ",sol[ct]);
}
printf("\n");
exit(0);
}
Explorar(sol,n+1,0);
}
if (ct==NUM_REINAS-1){
do{
n=n-1;
}while(sol[n]==NUM_REINAS-1);
if(n<0){
printf("No hay solucin \n\n");
exit(1);
}
Explorar(sol,n,sol[n]+1);
}
ct=ct+1;
}while(1);
}
int Comprueba(int *sol, int n){
int ct;
for(ct=0;ct<n;ct++){
if (sol[ct]==sol[n]) return 0;
if (sol[ct]-sol[n]==ct-n) return 0;
if (sol[ct]-sol[n]==n-ct)return 0;
}
return 1;
}

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 28
11.2. CAPTURA DE LA EJECUCIN DEL PROGRAMA.

11.3. EXPLICACIN DEL PROGRAMA.
El programa va colocando las reinas en el vector sol[]. Si sol[0]=2 quiere decir que se coloca
la reina 0 en la fila 2. Cada reina tiene asignado el mismo nmero que la columna donde est
situada.
La funcin Comprueba tiene como argumentos el vector sol[] y un nmero entero n y esta
funcin retorna 0 en el caso que la reina n amenace a alguna reina ya colocada.
Hay dos posibilidades para que la funcin retorne un 0 (amenaza):
misma fila;
misma diagonal.
La funcin principal que hace todo el clculo es la funcin Explorar(). Es una funcin
recursiva ya que se llama a s misma. La funcin Explorar(sol, n, ct) se llama si las n reinas
anteriores a n (0, (n-1)) ya estn bien colocadas y lo que se hace es explorar si la posicin ct es
admisible para la reina n. Si esta posicin es buena y no se ha colocado ya la ltima reina, explora
la siguiente reina desde la posicin 0.



MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 29
12. EJERCICIOS.
1) Funcin recursiva de la potencia entera de un nmero.
Escribiremos una funcin, el protocolo de la cual ser:
double pot(double base, int exponente)
Esta funcin debe calcular de forma recursiva el nmero que resulta de elevar la base al
exponente. Por eso debemos utilizar que b
n
=bb
n-1
.
Denominaremos al programa m4e1.c dentro de la carpeta Mdulo_4.
2) Curiosidad matemtica.
Tomando como base el ejercicio anterior, realizaremos otro
que muestre una salida como la que hay a continuacin :



El programa deber contener una funcin recursiva que
calcule 1 elevado 2, 11 elevado 2, 111 elevado 2, 1111 elevado
2, Haremos la pirmide slo para 8 filas
Denominaremos al programa m4e2.c dentro de la carpeta Mdulo_4.
3) Adivina el nmero.
El programa generar un nmero aleatorio entre 1 y 1000 y el usuario intentar adivinarlo.
La aplicacin en todo momento apoyar al usuario, a partir del nmero que crea que es,
mostrando entre qu nmeros se encuentra el dato a adivinar.
El programa ha generado un nmero entre o y 1000.
Cul crees que es? 456
El nmero se encuentra entre 456 y 1000.
Cul crees que es? 700
El nmero se encuentra entre 456 y 700.
Cul crees que es? 500
El nmero se encuentra entre 500 y 700.
Cul crees que es? 625
El nmero se encuentra entre 500 y 625.
Cul crees que es? 615
El nmero se encuentra entre 615 y 625.
Cul crees que es? 619
CORRECTO. Has adivinado el nmero en el intento nmero 6.
Denominaremos al programa m4e3.c dentro de la carpeta Mdulo_4.
4) Sucesin de Fibonacci.
Siguiendo las indicaciones del resumen terico respecto a la sucesin de Fibonacci,
haremos un programa que muestre los n primeros valores de esta sucesin, siendo n un nmero
entero entrado por teclado.
Denominaremos al programa m4e4.c dentro de la carpeta Mdulo_4.
MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 30
5) Simulacin del lanzamiento de tres dados.
Siguiendo el esquema de la prctica 6, haremos una simulacin del lanzamiento de tres
dados 100.000 veces y verificaremos de esta forma que la probabilidad de extraer suma 9 y suma
10 es diferente. Slo faltar que se contabilicen las veces que sale 9 y 10 y haremos que salga por
pantalla las frecuencias absolutas y relativas de los acontecimientos: suma 9 y suma 10.
Denominaremos al programa m4e5.c dentro de la carpeta Mdulo_4.
12.1. PROBLEMAS COMPLEMENTARIOS.
6) Clculo de un rea por el mtodo de aceptacin - rechazo.
Siguiendo las pautas de la prctica 7 encontraremos
el rea del recinto del cuadrado de lado 2 que queda por
encima de la parbola y = x
2
.
El dibujo del rea que se quiere calcular es la parte
sombreada del dibujo adjunto. Los vrtices del rectngulo
son (-1, 0), (-1, 1), (1, 1) y (1, 0).
El proceso ha de consistir en generar puntos del rectngulo; es decir, pares de nmeros
aleatorios:
x, un nmero aleatorio entre -1 y 1 (exactamente igual que en la prctica 7).
y, un nmero aleatorio entre 0 y 1.
Los puntos de la zona de aceptacin cumplen que y>x
2
.
Podremos comprobar el resultado obtenido con el valor exacto de esta rea que es
4
/
3
.
Denominaremos al programa m4e6.c dentro de la carpeta Mdulo_4.
7) Nmeros combinatorios (II).
En el ejercicio 3 se ha propuesto un programa que contenga una funcin que calcule un
nmero combinatorio utilizando la funcin factorial. En muchos casos, el clculo de un nmero
combinatorio se puede simplificar si en lugar de utilizar la frmula:
(



utilizamos esta otra equivalente:
(


La razn es que n! puede ser mucho ms grande que el numerador de la frmula anterior y,
por este motivo, se puede producir un error de sobrecarga (overflow), adems, el tiempo de
clculo de la segunda frmula es ms pequeo.
Haremos un programa que implemente la funcin combinatoria de la segunda forma y
compararemos los resultados con la funcin del ejercicio 3 con nmeros combinatorios como:
(

)
Denominaremos al programa m4e7.c dentro de la carpeta Mdulo_4.

MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 31
8) Nmeros combinatorios (III).
Todava hay otra forma de implementar el clculo de los nmeros combinatorios, se trata
de utilizar la relacin siguiente:
(

) (

) (

)
Por tanto, se puede definir una funcin recursiva en la cual, los casos de salida sean:
Si n=m (

) ; y si m=0 (

) . Implementaremos esta funcin.


Denominaremos al programa m4e8.c dentro de la carpeta Mdulo_4.
9) Clculo de nmeros combinatorios.
Utilizando la funcin factorial definida en el resumen terico, se debe construir una funcin
que calcule el valor del nmero combinatorio: (

)
Sabiendo que se calcula utilizando la frmula:
Este nmero representa el nmero de combinaciones diferentes de m elementos que se
pueden formar con n elementos.
Por ejemplo, con 4 elementos hay 6 combinaciones:
Si los 4 elementos son {a, b, c, d}, estas son las 6 combinaciones posibles:
{a, b}, {a, c}, {a, d}, {b, c}, {b, d}, {c, d}.
Haremos un programa que compruebe que n sea ms grande o igual que m.
Denominaremos al programa m4e9.c dentro de la carpeta Mdulo_4.
10) Juego del siete.
Tambin denominado Over and Under Seven, es un juego de casino de accin rpida en el
cual las apuestas se determinan con una sola tirada de dos dados.
Denominaremos al programa m4e10.c dentro de la carpeta Mdulo_4.
Objetivo del juego.
Apostar a que saldr un nmero mayor (MAS), menor (MENOS) o igual (SIETE) a 7. Tras
una tirada de dados el casino pagar las apuestas de aquellos que han acertado (en el caso
de ser la apuesta igual a 7, pagar 3 a 1, o 4 a 1, segn est establecido) y se quedar con
las de aquellos que han fallado.
Desarrollo del juego.
Tras realizar la apuesta los jugadores, el programa lanzar los dos dados y dar la
suma. A continuacin pagar o no las apuestas de los diferentes jugadores.
En todo momento en el monitor se mostrarn los siguientes datos, actualizndose en
cada jugada:
Saldo actual de cada jugador.
Apuesta de la jugada.
Advertencia.
Hay 36 combinaciones posibles en un tiro de dos dados. De estas combinaciones,
quince son de MENOS, quince de MAS y seis de SIETE.
(



MP 11 UF 01 Mdulo 4 Fundamentos Programacin. Pgina 32
11) El ordenador adivina el nmero.
Tomando como base el ejercicio 3 de este mdulo, el programa generar un nmero
aleatorio entre 1 y 1000 y en este caso es el ordenador quin acabar encontrando el nmero. La
aplicacin en todo momento mostrar el desarrollo de la partida.
Denominaremos al programa m4e11.c dentro de la carpeta Mdulo_4.
12) La raz digital de un nmero.
La raz digital de un nmero es la que resulta de sumar sus dgitos y, si esta suma es ms
grande o igual a 10, volver a hacer la suma de los dgitos de esta suma y as sucesivamente hasta
obtener un nmero de un dgito.
Por ejemplo: AD(1523)=AD(1+5+2+3)=AD(11)=2
AD(42513)=AD(4+2+5+1+3)=AD(15)=6
Crearemos un programa que escriba la raz digital de un nmero natural.
Denominaremos al programa m4e12.c dentro de la carpeta Mdulo_4.

También podría gustarte