Fundamentos de Informática

Ingeniería Técnica Industrial. E.U. Politécnica

EJERCICIOS RESUELTOS

Los ejercicios resueltos de la siguiente relación no están relacionados con la lista de ejercicios propuestos de cada tema (la cual puedes encontrar aquí).


Ejercicios sobre funciones y modularización de programas


  1. Realizar una función fibonacci(n) que calcule el término n-ésimo de la sucesión de Fibonacci, dada por:
         fibonacci (0) = 0
         fibonacci (1) = 1
         fibonacci (i) = fibonacci (i-1) + fibonacci (i-2)
    

    Diseñar un programa principal que acepte valores de n desde el teclado, utilice la función anterior y escriba el resultado en la pantalla. El programa finalizará cuando se introduzca un valor negativo.

    Solución:

    /****************************/
    /*  Sucesión de Fibonacci.  */
    /****************************/
    #include <stdio.h>
    
    unsigned long fibonacci (int);
    
    /***** Función Principal *****/
    void main () {
      int x;
    
      printf ("Introducir número: ");
      scanf ("%d", &x);
    
      while (x >= 0) {
         printf ("Fibonacci (%d) = %lu.\n\n", x, fibonacci (x));
         printf ("Introducir número: ");
         scanf ("%d", &x);
      }
    
      puts ("\nFin del programa.");
    }
    
    /* Devuelve el término n-ésimo de la sucesión de Fibonacci */
    unsigned long fibonacci (int n) {
      unsigned long s1, s2, s3;
      unsigned i = 2;
    
      if (n == 0) return 0; /* fibo (0) = 0 */
      if (n == 1) return 1; /* fibo (1) = 1 */
    
      s1 = 0;
      s2 = 1;
    
      while (i <= n) {
         s3 = s1 + s2;
         s1 = s2;
         s2 = s3;
         i++;
      }
    
      return s3;
    }
    

  2. Implementar una función, Digit(N,num) que devuelva el dígito N-ésimo de un número num de tipo long unsigned int, teniendo en cuenta que el dígito 0 es el dígito más a la derecha (el menos significativo). La función devolverá -1 si el número no tiene suficientes dígitos.

    Solución:

    /****************************/
    /* Tema 5: Ejercicio 18     */
    /****************************/
    #include <stdio.h>
    
    /***** Devuelve el dígito N-ésimo del número num *****/
    int Digit (unsigned N, long unsigned num){
        while (N!=0 && num!=0){
            num=num/10;
            N--;
        }
        if (num==0)
             return -1;
        return num%10;
    }
    
    /***** Función Principal *****/
    void main(){
        unsigned long numero;
        unsigned posicion=0;
        int digito;
    
        printf("\n- Número: ");
        scanf("%lu",&numero);
    
        while ( (digito=Digit(posicion,numero)) >= 0){
            printf("\nEl dígito en la posición %u es: %i.",digito);
            posicion++;
        }
    }
    

    Se podía resolver también utilizando la función potencia para hallar pow(10,N), pero si N es muy grande, el resultado puede ser excesivamente grande. De la forma propuesta se evita ese posible error. Por otra parte, la función Digit() falla si el número es cero y la posición solicitada es la cero. En ese caso debería devolver el dígito cero y, sin embargo, devuelve -1. Para solucionar ese error basta con poner un if antes del bucle while.


  3. Programar una función para resolver una ecuación de segundo grado: ax2 + bx + c = 0. Además de las soluciones (s1 y s2 utilizando un paso de argumentos por referencia), la función devolverá un valor que indique el tipo de solución encontrada: 0 si no es ecuación de segundo grado (a=0), 1 si existe una solución doble (s1 y s2, con s1=s2), 2 si existen dos soluciones distintas (s1 y s2) y 3 si existen dos soluciones imaginarias (s1+s2i y s1-s2i).

    Solución:

    /**************************************/
    /* Resolver Ecuación de segundo grado */
    /**************************************/
    #include <stdio.h>
    #include <math.h>
    
    /* Función para resolver una ecuación de segundo grado: ax^2 + bx + c = 0 */
    /* Devuelve: 0 si no es ecuación de segundo grado (a=0)                   */
    /*           1 Existe una solución doble: s1 y s2 (con s1=s2)             */
    /*           2 Existen dos soluciones distintas: s1 y s2                  */
    /*           3 Existen dos soluciones imaginarias s1+s2i y s1-s2i         */
    unsigned Ecuacion2grado (double a, double b, double c,
                             double *s1, double *s2){
      double radicando;
    
      if (a==0)
         return 0;
    
      radicando=b*b-4*a*c;
      if (radicando==0){ /* Solución doble */
         *s1 = *s2 = -b/(2*a);
         return 1;
      }
      if (radicando>0){ /* Dos soluciones */
         radicando=sqrt(radicando);
         *s1 = (-b+radicando) / (2*a);
         *s2 = (-b-radicando) / (2*a);
         return 2;
      }
      /* Soluciones imaginarias:                      */
      *s1=-b/(2*a);               /* Parte Real       */
      *s2=sqrt(-radicando)/(2*a); /* Parte Imaginaria */
      return 3;
    }
    
    /***** Función Principal *****/
    void main(){
      double a,b,c,s1,s2;
    
      puts("\n-Introduce los coeficientes de una ecuación de segundo grado:");
      printf("\n- Número a: "); scanf("%lf",&a);
      printf("\n- Número b: "); scanf("%lf",&b);
      printf("\n- Número c: "); scanf("%lf",&c);
    
      switch(Ecuacion2grado(a,b,c,&s1,&s2)){
        case 0: puts("\n* No es una ecuación de segundo grado.");
                break;
        case 1: printf("\n* Solución real doble: %lf.\n",s1);
                break;
        case 2: printf("\n* Dos soluciones reales: %lf y %lf.\n",s1,s2);
                break;
        case 3: printf("\n* Dos soluciones imaginarias: %lf + %lfi.",s1,s2);
                printf("\n                              %lf - %lfi.\n",s1,s2);
      }
    }
    

  4. Dattatreya Kaprekar (1905-1986) fue un matemático indio que nunca escribió nada de alto nivel y sus trabajos no han dado origen a ninguna investigación especial ni tienen ninguna utilidad importante, pero son sorprendentes y originales. Entre sus trabajos está el siguiente:

    Lo curioso es que independientemente del número A elegido, al final siempre se llega al mismo número. Hacer un programa que averigue ese número final (6174).

    Fases del programa: Primero hacer una función KaprekarOrden(A) que dado el número A como único argumento, nos devuelva el número D. Esa función sólo efectuará un ciclo. El programa principal pedirá un número y aplicará la función sucesivamente hasta que el resultado de la función sea igual a su argumento, es decir, hasta que ya no tenga sentido seguir aplicando la función porque siempre obtenemos el mismo número. En ese momento el programa mostrará ese número y terminará. Mostrar también el número de pasos necesarios para obtener ese número a partir del número original.

    Solución:

    /************************/
    /* Tema 5: Ejercicio 12 */
    /************************/
    #include <stdio.h>
    
    /* Calcular los valores mayor, medio y menor de 3 números */
    void MayorMenorDe3 (unsigned a, unsigned b, unsigned c,
         unsigned *Mayor, unsigned *Medio, unsigned *Menor){
      if (b>a)
         if (c>a){
            *Menor=a;
            if (b>c){
               *Mayor=b;
               *Medio=c;
            }
            else {
               *Mayor=c;
               *Medio=b;
            }
         }
         else{
            *Menor=c;
            *Mayor=b;
            *Medio=a;
         }
      else
         if (a>c){
            *Mayor=a;
            if (b>c){
               *Medio=b;
               *Menor=c;
            }
            else {
               *Medio=c;
               *Menor=b;
            }
         }
         else{
            *Menor=b;
            *Mayor=c;
            *Medio=a;
         }
    }
    
    /* Función para resolver el problema de Kaprekar de
       dividir un número de 4 cifras en dos ordenando sus cifras */
    unsigned KaprekarOrden (unsigned A){
      unsigned A1,A2,A3,A4, /* Dígitos del número A */
               O1,O2,O3,O4; /* Dígitos ordenados de A */
    
      A1=A/1000; /* Calcular dígitos de A */
      A2=(A/100)%10;
      A3=(A/10)%10;
      A4=A%10;
    
      /* Ordenar los dígitos crecientemente */
      if (A1>=A2 && A1>=A3 && A1>=A4){
         O1=A1;
         MayorMenorDe3(A2,A3,A4,&O2,&O3,&O4);
      }
      else if (A2>=A1 && A2>=A3 && A2>=A4){
         O1=A2;
         MayorMenorDe3(A1,A3,A4,&O2,&O3,&O4);
      }
      else if (A3>=A1 && A3>=A2 && A3>=A4){
         O1=A3;
         MayorMenorDe3(A1,A2,A4,&O2,&O3,&O4);
      }
      else {
         O1=A4;
         MayorMenorDe3(A1,A2,A3,&O2,&O3,&O4);
       }
    
      return (O1*1000 + O2*100 + O3*10 + O4) -
             (O4*1000 + O3*100 + O2*10 + O1);
    }
    
    /* Función Principal: Leer un número y calcular en cuantos pasos
       se obtiene un número tal que su siguiente es ese mismo número */
    void main(){
      unsigned actual,siguiente,pasos=0;
    
      do{ printf("\n- Número de 4 cifras (o menos): ");
          scanf("%u",&siguiente);
      }while (siguiente>9999);
    
      do{
        actual=siguiente;
        siguiente=KaprekarOrden(actual);
        pasos++;
      }while (siguiente!=actual);
    
      if (actual==0)
         puts("\nEl número tiene todos sus dígitos iguales.");
      else{ /* Sale siempre 6174 */
         printf("\nEl número es %u.",actual);
         printf("\nTotal de pasos: %u.",pasos);
      }
    }
    

    Para ordenar los 4 dígitos se ha utilizado una función vista anteriormente para ordenar 3 números. Teniendo esa función, se averigua el mayor de todos y se ordenan los tres siguientes.


  5. Escribir una función CuentaChars()que lea una cadena de caracteres acabada en un punto, para calcular la posición de la primera y la última ocurencia de un determinado carácter ch. La función tendrá 3 argumentos: El primero será el carácter ch y los dos siguientes serán utilizados para devolver los valores indicados (usando un paso de parámetros por referencia). Ambos valores serán cero si ch no aparece ninguna vez en la cadena de caracteres leida.

    Además, la función devolverá (con return) el número de veces que aparece el carácter ch. El programa de prueba principal simplemente leerá el carácter ch, llamará a la función CuentaChars() y mostrará los 3 valores resultantes.

    Solución:

    #include <stdio.h>
    
    /***** ***** ***** ***** *****
    Lee una cadena de caracteres acabada en un punto, para calcular
    la posición de la primera y la última ocurencia del carácter ch.
    Ambos valores serán cero si ch no aparece ninguna vez.
    Devuelve el número de veces que aparece ese carácter.
    ***** ***** ***** ***** *****/
    unsigned CuentaChars (char ch, unsigned *primero, unsigned *ultimo){
      char leido;
      unsigned Total_Leidos=0, /* Total de caracteres leídos */
               Total_ch=0;     /* Total de caracteres ch     */
    
      *primero = *ultimo = 0; /* Por si no hay ocurrencias de ch */
      fflush(stdin);          /* Limpiar el buffer de teclado    */
    
      do{
        leido=getchar();
        Total_Leidos++;
        if (leido==ch){
           *ultimo=Total_Leidos;
           Total_ch++;
           if (Total_ch==1)
              *primero=Total_Leidos;
        }
      }while(leido!='.');
      return Total_ch;
    }
    
    /***** ***** ***** Función Principal ***** ***** *****/
    void main(){
      char caracter;
      unsigned Leidos, first, last;
    
      printf("\n- Dame el carácter a buscar/contar: ");
      caracter=getchar();
    
      printf("\n- Dame el texto donde buscar: ");
      Leidos=CuentaChars(caracter,&first,&last);
    
      printf("\n- Resultados:");
      printf("\n   * Veces que aparece el carácter: %u.",Leidos);
      printf("\n   * Primera y última vez: %u y %u.",first,last);
    }
    

  6. Realizar un programa que simule el siguiente juego: Un jugador tira dos dados. Si en la primera tirada la suma de los dos es 7 u 11 el jugador gana. Si es 2, 3 ó 12 pierde. Si es cualquier otra puntuación el jugador debe seguir tirando los dados hasta que bien repita la primera puntuación en cuyo caso gana la partida, o bien salga un 7 y pierda.

    Solución:

    #include <stdio.h>
    #include <stdlib.h> /* srand(): inicializa el generador de números aleatorios */
                        /* rand(): genera un número aleatorio entre 0 y RAND_MAX */
    #include <time.h>   /* time(): Función utilizada para inicializar srand() */
    
    int tirada(void);
    
    void main () {
      int estadoJuego, suma, miPunto;
      srand(time(NULL));
      suma = tirada();  /* Primera tirada del dado */
      switch(suma) {
        case 7:                   /* Gana en la primera tirada */
        case 11:
            estadoJuego = 1;
            break;
        case 2:                   /* Pierde en la primera tirada */
        case 3:
        case 12:
            estadoJuego = 2;
            break;
        default:                  /*  Se guarda la puntuación con la que se va a
                                      jugar la partida*/
            estadoJuego = 0;
            miPunto = suma;
            printf ("Puntuación: %d\n", miPunto);
            break;
      }
    
      /**************************************************************
        Se realizan tiradas hasta que:
        1.- Se consiga la misma puntuación de la primera tirada (gana)
        2.- Salga un 7 (pierde)
      **************************************************************/
      while (estadoJuego == 0) {
        suma = tirada();
        if (suma == miPunto)
            estadoJuego = 1;
        else
           if (suma==7)
            estadoJuego = 2;
      }
      if (estadoJuego == 1)
        printf("Jugador gana\n");
      else
        printf("Jugador pierde\n");
    } /* Fin main */
    
    /***************************************************************************
      Función tirada: simula la tirada de dos dados y devuelve la suma de ambos
     ***************************************************************************/
    int tirada(void) {
      int dado1, dado2, suma;
    
      dado1 = 1 + (rand() % 6);
      dado2 = 1 + (rand() % 6);
      suma = dado1 + dado2;
      printf("Tirada del jugador: %d + %d = %d\n", dado1, dado2, suma);
    
      return suma;
    }
    

  7. Dos números a y b se dice que son amigos si la suma de los divisores de a (salvo él mismo) coincide con b y viceversa. Diseña un programa que tenga como entrada dos números naturales n y m y que muestre en la pantalla todas las parejas de números amigos que existan en el intervalo determinado por n y m. Hágalo programando distintas funciones.

    Solución 1:

    /* Ejercicio 17 del tema 5 */
    #include <stdio.h>
    #include <conio.h>
    
    /* Declaraciones previas de las funciones.  Esto permite
       codificarlas después de la funcion principal main(). */
    
    int divisor(int num1,int num2);
      /* Devuelve un número distinto de 0 si num2 divide a num1 */
    int sumadiv(int num);
      /* Devuelve la suma de los divisores de un número num, sin contar a num */
    int amigos(int num1,int num2);
      /* Devuelve un numero distinto de 0 si los números num1 y num2 son amigos */
    
    
    void main(){
    int i,m,n;
    
      clrscr();        /* Para limpiar la pantalla */
      do{
         printf("\nIntroduzca el primer numero : ");
         scanf("%i",&n);
         printf("\nIntroduzca el segundo numero : ");
         scanf("%i",&m);
      }while (n>=m);     /* De esta manera aseguramos que n < m */
    
      for (i=n;i<m;i++){
         int j;             /* Variable local al bucle for */
         for (j=i+1;j<=m;j++){
           if (amigos(i,j)) printf ("\n Los dos numeros %d y %d son amigos",i,j);
         }
      }
    }  /* Fin de la función main() */
    
    int divisor(int num1,int num2){
       return(num1%num2==0);
    }
    
    int sumadiv(int num){
       int cont,suma=0;
       for(cont=1;cont<num-1;cont++){
          if(divisor(num,cont)) suma+=cont;
       }
       return(suma);
    }
    
    int amigos(int num1,int num2){
       return ((sumadiv(num1)==num2)&&(sumadiv(num2)==num1));
    }
    

    Solución 2 (mejor):

    /* Ejercicio 17 del tema 5. Otra solución */
    #include <stdio.h>
    #include <conio.h>
    
    /* Función que devuelve la suma de los divisores de numero */
    int sumadivisores (int numero){
      int i,suma=0;
      for (i=numero-1;i>=1;i--)
         if (numero%i==0) suma+=i;  /* Es decir, suma = suma + i; */
      return suma;
    }
    
    void main (){
      int num1,num2,a,b,c;
    
      clrscr();
      printf("\nIntroduce el primer n£mero:");
      scanf("%d",&num1);
      printf("\nIntroduce el segundo n£mero:");
      scanf("%d",&num2);
      if (num1>=num2)
         printf("\nError: el intervalo no es valido.");
      else{
         for(a=num1;a<=num2;a++){
           c=sumadivisores(a);
           if ((c>=num1) && (c<=num2))
              /* Si la suma de los divisores está en el rango [num1,num2]
                 entonces, comprobar si se cumple la igualdad contraria: */
              if ((sumadivisores(c)==a) && (a<c))
                 /* Se compara que a<c para evitar que una pareja salga 2 veces */
                 printf("\nPareja:[%d,%d]",a,c);
           }
      }
    } /* main() */
    

  8. Escribir una función sumanumeros() que lea una cadena de números separados por espacios acabada en un punto. La función debe devolver la suma de todos los números de la cadena y además debe aceptar tres argumentos: el primero será un carácter que contiene un dígito (del 0 al 9), el segundo argumento devolverá el número de veces que ese dígito aperece en la cadena de entrada y el tercer argumento devolverá el número de números que se han sumado en la cadena de entrada. Observa que los dos últimos parámetros deben ser pasados por referencia (es decir por dirección).

    Por ejemplo, si la cadena de entrada es: 22 18 1122 8.

    La función es usada tal como:

       suma_num=sumanumeros('2',&num_veces_digito,&numero_numeros);
    

    Al terminar la ejecución de la misma tendremos los siguientes valores:

       sum_num==1170,   (es decir 22+18+1122+8)
       num_veces_digito==4,  (es decir el 2 aparece 4 veces)
       numero_numeros==4, es decir hay cuatro numeros en la entrada
    

    Solución:

    #include <stdio.h>
    #include <conio.h>
    #include <ctype.h>
    
    int sumanumeros(char dig, int *num_veces_dig, int *num_numeros) {
       char ch;
       int numero=0, sumanumeros=0;
    
       *num_veces_dig=0;
       *num_numeros=0;
    
       printf ("	Escribe la cadena de caracteres: ");
       ch = getchar();
       while (ch != '.') {
    	if (ch == dig) *num_veces_dig=*num_veces_dig+1;
    	if (ch == ' ') {
    	    *num_numeros=*num_numeros+1;
    	    sumanumeros=sumanumeros+numero;
    	    numero=0;
    	}
    	else
    	    numero=numero*10+(ch-'0');
    	ch=getchar();
       }
       /* Para sumar el ultimo numero antes del '.' */
       *num_numeros=*num_numeros+1;
       sumanumeros=sumanumeros+numero;
       return(sumanumeros);
    } /* Fin de la FUNCION sumanumeros() */
    
    
    /* funcion principal */
    void main(){
      char digito;
      int suma_num, num_veces_digito=0, numero_numeros=0;
    
      clrscr();
      printf(" Introduzca el digito a buscar: ");
      digito=getchar();
      fflush(stdin);    /* Limpia el buffer: Elimina del buffer el 
                           retorno de carro leído tras el dígito. */
    
      suma_num=sumanumeros(digito,&num_veces_digito,&numero_numeros);
    
      printf("\n  Se han sumado %d numeros ",numero_numeros);
      printf("\n  El digito %c aparece %d veces en total",digito,num_veces_digito);
      printf("\n  La suma de todos los n£meros de la cadena es: %d",suma_num);
    } /* fin de la función principal */