PI-ITBA / 2024_02

Consultas 2C 2024
4 stars 0 forks source link

TP7_ej6 #76

Open mipipet opened 5 hours ago

mipipet commented 5 hours ago

Hola!! Quería consultar si esta resolución del ejercicio 6 de la guia 7 esta bien y es eficiente. Lo corrí bastantes veces y no pude detectar ningún error muy evidente en la ejecución. Gracias!!


#include <stdio.h>
#include "random.h"
#include "getnum.h"
#define X 3

void generaAleatorio(int incognita[]); 
int elegirNivel(); 
void leerNumero(int num[]); 
int coincidenumero(int num[], int incognita[]); 
int cantidadBien(int incognita[], int num[]); 
int cantidadRegular(int incognita[], int num[]); 

int main(){
    int nivel=elegirNivel(); 
    int incognita[X]; 
    int num[X];
    generaAleatorio(incognita);
    int ans=0; 
    for(int i=0; i<nivel && !ans; i++){
        leerNumero(num); 
        ans=coincidenumero(num, incognita);
        if(i==nivel-1){
            printf("El número era "); 
            for(int i=0; i<X; i++){
                printf("%d", incognita[i]); 
            }
            putchar('\n');
        }
    }

    return 0; 
}

void generaAleatorio(int incognita[]){
    srand(time(NULL));
    int aux[9]={0}, num; 
    for(int i=0; i<X; i++){
        do
        {
            num=randInt(1,9);
        } while (aux[num-1]==1);

        incognita[i]=num; 
        aux[num-1]=1; 
    }
    return; 
} 

int elegirNivel(){
    int num, true=0;

    do
    {
        num=getint("Ingrese un nivel del 1-10\n"); 
        if(num>0 && num<=10){
            true=1; 
        }

    } while (!true);

    return num;  
} 

void leerNumero(int num[]){

    int TRUE=0, n=0, aux, ok;

    do
    {   
        int vecAux[9]={0};
        printf("Ingrese un número de %d dígitos\n", X);
        scanf("%d", &aux);
        ok=1;
        for(int i=X-1; i>=0 && ok; i--){
            if(vecAux[aux%10]==0){
                num[i]=aux%10; 
                aux=aux/10; 
                vecAux[num[i]]=1; 
            }else{
                ok=0; 
            }
            if(aux==0 && i!=0){
                ok=0; 
            }
        }
        if(ok){
            TRUE=ok; 
        }
    } while (!TRUE);

}

int coincidenumero(int num[], int incognita[]){
    int bien, ans;;
    if((bien=cantidadBien(incognita, num))==X){
        ans=1; 
        printf("El número ingresado es correcto\n"); 
    }else{
        printf("Tiene %d digitos bien y %d regular\n", bien, cantidadRegular(incognita, num));
        ans=0; 
    }
    return ans; 
}

int cantidadBien(int incognita[], int num[]){
    int bien=0; 
    for(int i=0; i<X ; i++ ){
        if(incognita[i]==num[i]){
            bien++; 
        }
    }
    return bien; 
}

int cantidadRegular(int incognita[], int num[]){
    int regular=0; 
    int aux[9]={0}; 
    for(int i=0; i<X ; i++ ){
        for(int j=0; j<X; j++){
            if(incognita[i]==num[j] && i!=j && aux[num[j]-1]==0){
                aux[num[j]-1]=1; 
                regular++; 
            }
        }
    }
    return regular; 
} 
``
marcelogarberoglio commented 5 hours ago

En líneas generales está bien pero algunas cosas se pueden mejorar

Por la forma de generar aleatorio te copio lo que hace un rato acoté en el issue #75

Estás verificando si un un dígito ya salió o no. Eso puede servir si tu número tiene muy pocos dígitos, pero qué pasa si X pasa a ser 7. Y algo similar pasará cuando tengan que programar el bingo, al extraer una bolilla del bolillero. Si la solución es similar a esta sería como si cuando sale una bolilla la vuelven a meter, y cada vez que sale una preguntan si ya salió o no, a medida que avanza el juego se pone muy lento. Podrías generar un vector con todos los valores a usar y después una de dos:

1) Mezclar el vector y extraer los primeros X valores 2) Ir obteniendo en forma aleatoria el índice, primero entre 0 y 8, si sale 3 reemplazás vecAux[3] con vecAux[8], luego un aleatorio entre 0 y 7, etc.

A lo cual agrego: randomize debería llamarse una sola vez en main, porque lo que garantiza es que no se elijan los mismos números en cada ejecuciíón del programa.

En cantidadRegular me parece que el uso del vector aux está de más.

No es necesario usar scanf para leer un número, pueden seguir usando getint, getdouble, etc

Este código

do
    {
        num=getint("Ingrese un nivel del 1-10\n"); 
        if(num>0 && num<=10){
            true=1; 
        }

    } while (!true);

se puede simplificar así

do    {
        num=getint("Ingrese un nivel del 1-10\n"); 

    } while (num <1 || num > 10);

además el nombre "true" para una variable es confuso, de hecho si se usa stdbool.h existen constantes que se llaman true y false, entonces al leer un código en C y ver "true" uno espera que sea esa constante, y no una variable que puede valer 1 o 0 Algo similar en leerNumero, ahí con el agravante de que la variable está escrita en mayúsculas (TRUE), que por convención se usa para definir constantes