Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: marsicobetre en 22 Octubre 2015, 20:49 pm



Título: numero odioso NUEVO!
Publicado por: marsicobetre en 22 Octubre 2015, 20:49 pm
hola,

tengo una tranca realizando un programa en devc++ y quisiera saber si me pueden ayudar. Tengo el programa casi finalizado pero me falta una cosa, y no lo logro dar

Este es el enunciado
Un número odioso es un número que, cuando se convierte a base 2, tiene un número impar de unos. Por ejemplo, son números odiosos: el 1, el 2 (10), el 4 (100), el 7 (111), el 8 (1000), el 11 (1011). Realice un programa que dado un valor entero K, devuelva la cantidad de números odiosos que hay entre 1 y K

ESTO ES LO QUE HE HECHO.. PERO ME TRANQUE..

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

int k;

void pedirInfo()
{
   do{
      printf("\n\n-Ingrese un numero entero positivo cualquiera: "); scanf("%d",&k);
      if(k<=0)//validacion del dato de entrada
      {
         printf("\a\n\t\t\tERROR: Ingrese un <numero entero positivo>\n");
      }
   }while(k<=0);
}

int main()
{
   printf("\t\t\tNUMERO ODIOSO\n");
   char resp;
   
   do{
      int x;
      pedirInfo();
   
      char cadena[1000];//primero calculo la cadena
      itoa(k,cadena,2); //genero la cadena
      printf("\nNumero <%d> convertido a base 2: %s\n" ,k,cadena); //muestro la cadena para comprobar que el calculo ha sido correcto
      
      //...
      
      int i, cantidad_de_1=0, cantidad_de_odiosos=0;
      for(i=1; i<=1000; i++)//calculo la cantidad de '1' que tiene la cadena, revisando posicion por posicion
      {
         if(cadena=='1') //revisa si la cadena en la posicion "i" tiene un '1'
         {
            cantidad_de_1++;
            /*
            si la cadena tiene un "1" lo cuenta
      
            los numeros odiosos son los que tiene una cantidad impar de numeros '1' dentro de la
            cadena
            */
         }
      }
      
      if(cantidad_de_1%2!=0)              
      {
         //calcula si la cantidad de '1' dentro del vector es impar, si es asi, es un numero odioso
         cantidad_de_odiosos++; // si la condicion del if es verdadera, cuento la cantidad de numeros odioso
         printf("\nCantidad de numeros odiosos: %d\n\n",cantidad_de_odiosos);
      }
      else
      {
         printf("\nEl numero %d no es un numero odioso\n\n",k);
      }
      
      //...
      
      do{
         printf("\n-Ingrese (s) si desea calcular otra cantidad de numeros odiosos, o (n) si desea finalizar el programa: "); scanf(" %c",&resp);
         if((resp!='s' && resp!='S') && (resp!='n' && resp!='N'))//validacion de los datos de entrada
         {
            printf("\a\n\t\t\tERROR: Ingrese (s)  o  (n)\n");
         }
      }while((resp!='s' && resp!='S') && (resp!='n' && resp!='N'));
      
   }while(resp=='s' || resp=='S');
   system("pause");
   return 0;
}


Título: Re: numero odioso NUEVO!
Publicado por: Seyro97 en 22 Octubre 2015, 23:34 pm
Antes de pasar al problema principal, te voy a dar unos cuantos consejos.

0º Usa etiquetas GeSHI!! Hará el código más vistoso y entendible y así recibirás antes la ayuda

1º No uses variables globales. Aunque estés haciendo un ejercicio, el uso de variables globales casi nunca está recomendado. En lugar de eso, podrías simplemente retornar el número:

Código
  1. int pedirInfo() {
  2.        int k = 0;
  3.  
  4. do {
  5. printf("\n\n-Ingrese un numero entero positivo cualquiera: "); scanf("%d", &k);
  6. if(k <= 0)//validacion del dato de entrada
  7. {
  8. printf("\a\n\t\t\tERROR: Ingrese un <numero entero positivo>\n");
  9. }
  10. } while(k <= 0);
  11.  
  12.        return k;
  13. }

2º Una variable de tipo 'int' ocupa 32 bits, es decir, 32 ceros o unos. Entonces, ¿por qué la cadena ocupa 1000 bytes? Mejor que solamente ocupe 33 bytes para así optimizar (el último carácter es nulo).

Código
  1. char cadena[33];

3º Teniendo en cuenta el paso anterior y que la cadena empieza por el cero, el ciclo for de la línea 32 se debería ver así:

Código
  1. for(i = 0; i < 32; i++)

4º Hay un error en la línea 34. A la hora de comparar los elementos de la cadena, comparas lo que es la cadena en sí, no los elementos:

Código
  1. if(cadena[i] == '1')

5º Lo que has pretendido hacer es contar la cantidad de 'números odiosos' que has introducido por el teclado, pero si reinicias esta cantidad en cada ciclo, entonces el contar no vale de nada jaja:

Código
  1. int i, cantidad_de_1 = 0, cantidad_de_odiosos = 0;

Las has declarado dentro del ciclo. Solución, poner esta sentencia antes de comenzar el ciclo

6º Después de cada ciclo, yo limpiaría el el buffer stdin. Para ello, al final del ciclo añade
Código
  1. fflush(stdin);
Además, tienes que reiniciar el número de unos en cada ciclo:
Código
  1. cantidad_de_1 = 0;

Después de haber dicho todo esto (espero de no haberme olvidado nada...) ESTO NO ES LO QUE PEDÍA EL EJERCICIO XDD. Lo que pedía el ejercicio es que comprobaras cuántos números odiosos había entre 1 y el número introducido...

PD. Extra: Hay una manera mucho más óptima de realizar este ejercicio. Te dejaré como pista que el ordenador de por sí guarda los datos en binario, no hace falta convertirlos... Puedes usar los operadores &, >> y todos los demás operadores binarios...

ESPERO HABERTE SIDO DE AYUDA!!


Título: Re: numero odioso NUEVO!
Publicado por: marsicobetre en 23 Octubre 2015, 05:08 am
hola! gracias por los consejos

había entendido mal el enunciado, pero ya logre hacer lo que me pedían

gracias, feliz día :)


Título: Re: numero odioso NUEVO!
Publicado por: do-while en 23 Octubre 2015, 13:13 pm
Si te interesa pensar en ello la versión recursiva para decidir si un número es odioso es interesante y sencilla.

Uno es odioso. Un número par será odioso si su mitad es odioso (si es par la representación binaria termina en cero, podemos dividirlo por dos y la mitad mantendrá el mismo número de unos). Un número impar en binario acaba en uno, así que sera odioso si al restarle uno no tenemos un número odioso (realmente al restarle uno tenemos un número par, así que sera odioso si al restarle uno y dividirlo por dos no tenemos un número odioso)

¡Saludos!