Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: LearningSpanishProgrammer en 9 Septiembre 2011, 03:30 am



Título: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 9 Septiembre 2011, 03:30 am
Normalmente, tenemos personas hacendo preguntas, pero, no esta vez

Este es un desafío para quen quiere: Dado un numero

Código:

int i = 389438

Tiene que imprimir el número invertido (en este caso 834983)

Sin necesidad de utilizar arreglos, tambíen no puede convertir a la cadena. No puede usar variable auxiliar y solo puede usar el 'for' una vez.


Título: Re: Un desafío para los interesados
Publicado por: raul338 en 9 Septiembre 2011, 03:48 am
Pensé que iba a ser mas difícil, de todas formas lo hice en vb :xD de la misma forma que se puede hacer en C++

http://pastebin.com/EhvJ6KAw (http://pastebin.com/EhvJ6KAw)


Título: Re: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 9 Septiembre 2011, 03:51 am
No puede usar variable auxiliar

Su resposta esta buena, pero su condición de parada no es muy buena


Título: Re: Un desafío para los interesados
Publicado por: raul338 en 9 Septiembre 2011, 04:01 am
Su resposta esta buena, pero su condición de parada no es muy buena
No entendí lo de "parada", pero en vb no se puede llamar a un for sin una variable, para eso usar While/Do (que son casos especiales del for :P)

Código
  1. int i = 389438;
  2. for (; i != 0;) {
  3.    // aca no recuerdo mucho la funcion para imprimir xD
  4.    printf(i % 10);
  5.    i = i / 10;
  6. }
  7.  


Título: Re: Un desafío para los interesados
Publicado por: rir3760 en 9 Septiembre 2011, 06:04 am
Supongo es un desafió para los principiantes, ¿Correcto?

Pero hay detalles. El primero es, dependiendo de la implementación, el valor 389438 puede ser de tipo "long". Y el segundo la aproximación con un "for" funciona pero no podría manejar el caso especial del valor cero (si se debe tener este en cuenta hay que cambiar el bucle "for" por un "do ... while").

Un saludo


Título: Re: Un desafío para los interesados
Publicado por: PiroskY en 12 Septiembre 2011, 17:24 pm
Estaría bueno que estén mejor explicadas las limitaciones.

Y también los casos para los cuales tendría que funcionar, a menos de que simplemente tenga que funcionar para ese numero.


Título: Re: Un desafío para los interesados
Publicado por: Alien-Z en 12 Septiembre 2011, 17:32 pm
Estaría bueno que estén mejor explicadas las limitaciones.

Y también los casos para los cuales tendría que funcionar, a menos de que simplemente tenga que funcionar para ese numero.

El que ha planteado esta cuestión le cuesta un poco expresarse en castellano, aun asi está muy bien explicado:

Dado el número: int i = 389438
-Tienes que imprimir dicha cifra invertida (en este caso 834983)
-No se pueden usar arrays
-No se puede convertir este número a cadena
-No se pueden usar variables auxiliares
-Solo se puede utilizar el bucle "for" una vez

Es muy sencillo, quizá asi lo veas más claro aunque ya lo ha resuelto raul338.

Citar
No entendí lo de "parada", pero en vb no se puede llamar a un for sin una variable, para eso usar While/Do

En C++ si se puede, es lo que has hecho en tu ejemplo, la única variable que has usado es la del propio número.

Saludos.


Título: Re: Un desafío para los interesados
Publicado por: PiroskY en 12 Septiembre 2011, 17:49 pm
No me refiero a eso.

Mira, este programa resuelve el problema:

int main()
{
    int i = 389438
    cout >> "834983";
    return 0;
}

Yo quería algo como; números positivos, cualquier numero, etc.


Título: Re: Un desafío para los interesados
Publicado por: Alien-Z en 12 Septiembre 2011, 17:56 pm
No me refiero a eso.

Mira, este programa resuelve el problema:

int main()
{
 int i = 389438
 cout >> "834983";
 return 0;
}

lol... ¡hay que imprimir el número invertido pero usando codes, no con un cout!  :xD

Citar
Yo quería algo como; números positivos, cualquier numero, etc.

Vamos a ver, tú tienes la variable "int i = 389438", y apartir de ahi con funciones, operaciones, bucles, etc. debes obtener el número inverso, es asi de sencillo.


Título: Re: Un desafío para los interesados
Publicado por: $Edu$ en 12 Septiembre 2011, 18:00 pm
Ya lo hiciste alienz o que? esque lo iba a hacer ahora, pero si ya lo hicieron 0 ganas xDD es usando mod y listo


Título: Re: Un desafío para los interesados
Publicado por: PiroskY en 12 Septiembre 2011, 18:00 pm
Yo entiendo lo que el desafió pide, pero vos no me estas entendiendo a mi.

No le veo sentido si se hace para un solo numero en particular.

Ahora, si dice para cualquier numero positivo, ahí ya mi programa dejaría de funcionar, pero para lo que el desafió pide, alcanza y sobra.


Título: Re: Un desafío para los interesados
Publicado por: Alien-Z en 12 Septiembre 2011, 18:08 pm
Ya lo hiciste alienz o que? esque lo iba a hacer ahora, pero si ya lo hicieron 0 ganas xDD es usando mod y listo

Si lo hice, además rir3760 ya ha posteado la solución en su segundo comentario.

Yo entiendo lo que el desafió pide, pero vos no me estas entendiendo a mi.

No le veo sentido si se hace para un solo numero en particular.

Ahora, si dice para cualquier numero positivo, ahí ya mi programa dejaría de funcionar, pero para lo que el desafió pide, alcanza y sobra.

No hombre, te vale con pedirle un valor al usuario y guardarlo en la variable, te calculará igualmente el número inverso. Vamos a cambiar un poco el enunciado, en vez de poner "int i = 389438" comienza con esto:

Código:
#include <iostream>
using namespace std;

int main()
{
int i;
cout << "Escribe un numero: ";
cin >> i;

//Ahora aqui escribe el code para obtener el numero invertido

cin.get();
return 0;
}

¿Asi mejor?.


Título: Re: Un desafío para los interesados
Publicado por: PiroskY en 12 Septiembre 2011, 18:11 pm
Mejoro, pero sigue sin la especificidad que busco.

Se van a ingresar números positivos y negativos? 0 ? solo uno de los dos?


Porque la solución posteada no funciona para números que no sean positivos.


Título: Re: Un desafío para los interesados
Publicado por: Alien-Z en 12 Septiembre 2011, 18:18 pm
Mejoro, pero sigue sin la especificidad que busco.

Se van a ingresar números positivos y negativos? 0 ? solo uno de los dos?


Porque la solución posteada no funciona para números que no sean positivos.

Consideramos que siempre va a ser positivo porque el ejercicio era sobre el número 389438.


Título: Re: Un desafío para los interesados
Publicado por: PiroskY en 12 Septiembre 2011, 18:18 pm
Yo también considero eso, pero no soy yo el que decide eso.


Título: Re: Un desafío para los interesados
Publicado por: ghastlyX en 12 Septiembre 2011, 19:53 pm
Para los que pedís más precisión en las restricciones o los que consideráis el ejercicio demasiado fácil, con permiso del autor lo podéis complicar un poco (bastante poco para cualquiera que sepa cuatro cosas de programación) siguiendo el siguiente enunciado, para el que la solución propuesta anteriormente no funcionará.

Problema:
Dado un número 0 <= n <= 10100 por la entrada estándar (stdin), se debe mostrar por la salida estándar (stdout) su número girado, tal que si los dígitos de n son a1, ..., an, los de su número girado serán an, ..., a1 (es la misma definición, formalizada un poco). Tened en cuenta por ejemplo que el girado de 100 es 001 y no 1.

Restricciones:
No se pueden utilizar arrays, structs, strings, clases ni nada similar, tan sólo los tipos de variables básicos de C/C++, es decir int, char, long long, etc.


Título: Re: Un desafío para los interesados
Publicado por: rir3760 en 13 Septiembre 2011, 15:04 pm
Un problema con un valor como ese (diez a la cien) es el rango. Seria mejor utilizar [0, ULONG_MAX] (hay que incluir <limits.h>) y de esa forma se mantiene dentro del estándar de C (C90).

Un saludo


Título: Re: Un desafío para los interesados
Publicado por: ghastlyX en 13 Septiembre 2011, 15:07 pm
El rango es totalmente intencionado, lo he puesto precisamente para que no coja en las variables numéricas primitivas. Ahí está la gracia del problema.


Título: Re: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 13 Septiembre 2011, 19:25 pm
ghastlyX, gracias, su problema es muy bueno

A lós demás que pensa el ejercicio no esta claro, recorde que interpretacion es una parte importante en la solucion de problema.

Pero, limitar a solo a números enteros positivos hubiera sido bueno. Lo siento por esto.


Título: Re: Un desafío para los interesados
Publicado por: rir3760 en 13 Septiembre 2011, 20:56 pm
El rango es totalmente intencionado, lo he puesto precisamente para que no coja en las variables numéricas primitivas. Ahí está la gracia del problema.
OK.

Un detalle es, al no haber limites, se estaria tratando no con un numero sino una secuencia de caracteres (solucion recursiva).

Un saludo


Título: Re: Un desafío para los interesados
Publicado por: Valkyr en 13 Septiembre 2011, 22:46 pm
Una solución (en pseudocódigo) podría ser algo así? :

Código:
VARIABLES
Caracter a;
Cadena reverso;

PROGRAMA
leer_caracter(a);
MIENTRAS(esDigito(a)) HACER
    concatena(a, reverso, reverso);
    leer_caracter(a);
FIN_MIENTRAS

Esto se podría hacer en C/C++ usando tipos básicos (bueno, para la cadena habría que usar char*). Se supone que leer_caracter(a) lee un carácter de la entrada estándar (se podría hacer en C++ con cin.get() y en C con get() me parece) y lo deja en la variable a. Luego, la condición del bucle comprueba que el valor introducido sea un dígito (esto se podría implementar fácilmente comprobando que el valor del carácter esté en el rango ASCII concreto de los números aunque en ya está implementado en la librería <cctype>). La función concatena lo que haría es, concatena la variable a al principio de reverso y guarda el resultado en reverso. Se vuelve a leer otro carácter y así sucesivamente.

¿Está bien la solución o he metido una buena gamba por algún sitio? xD

Saludos.


Título: Re: Un desafío para los interesados
Publicado por: rir3760 en 14 Septiembre 2011, 01:34 am
Segun los dos enunciados no pueden utilizarse arrays.

Un saludo


Título: Re: Un desafío para los interesados
Publicado por: Valkyr en 14 Septiembre 2011, 01:52 am
Pues hombre hasta donde yo se de C (que la verdad es más bien poco) char * no se considera un array, ¿O estoy equivocado?.

EDIT: Pensandolo ahora un poco mejor sí que se puede considerar como un array.

Saludos.


Título: Re: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 14 Septiembre 2011, 02:15 am
Valkyr, su error es muy común, el papel dual del puntero (como uno puntero para un char o un puntero para um arreglo del char). Es, en mi opiníon, un error del linguaje de programación.

No pasa nada.


Título: Re: Un desafío para los interesados
Publicado por: Valkyr en 14 Septiembre 2011, 02:32 am
Después de pensar una alternativa que no use char * sólo se me ocurre una función recursiva, es decir, esto:

Código
  1. #include<iostream>
  2. #include<cctype>
  3. using namespace std;
  4.  
  5. void procedimiento(){
  6. int caracter = cin.get();
  7. if(isdigit((char)caracter)){
  8. procedimiento();
  9. cout<<(char)caracter;
  10. }
  11. }
  12.  
  13. int main(void){
  14. procedimiento();
  15. }

y efectivamente funciona para el caso 100. Se podría cambiar el programa para que se pudiesen ingresar varios números ya que ahora mismo solo se puede ingresar uno. También si el número fuese excesivamente largo podría haber problemas con la pila ya que acumularía demasiadas llamadas a la función. ¿A alguien se le ocurre alguna alternativa?.

Saludos.


Título: Re: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 14 Septiembre 2011, 02:43 am
yo cometi un error, disconsiderar

EDIT: Estaba a hablar de mí proprio puesto


Título: Re: Un desafío para los interesados
Publicado por: Valkyr en 14 Septiembre 2011, 02:54 am
Ummm... si no me equivoco al hacer la llamada recursiva la variable caracter se guardará dentro de la pila, ya que es un valor que al volver de la llamada necesitamos y por tanto si se guarda en un registro del procesador debe asegurarse que al volver de la llamada el valor seguirá estando ahí, y si nos pusiesemos a guardar valores en registros distintos nos quedaríamos sin registros.

No se que código generará en ensamblador este programa, pero por lógica yo pienso que haría eso. Incluso puede ser que guarde más información todavía como por ejemplo el PC de la instrucción que realizó la llamada o cosas similares. Teniendo esto en cuenta si el número introducido es exageradamente grande podría provocar un overflow en la pila.

Saludos.


Título: Re: Un desafío para los interesados
Publicado por: Danyel_Casvill en 14 Septiembre 2011, 03:12 am
Eso parece una tarea dizfrasada... :silbar:


Título: Re: Un desafío para los interesados
Publicado por: LearningSpanishProgrammer en 14 Septiembre 2011, 04:27 am
Valkyr, tu estas correcto, yo escribí incorrectamente


Título: Re: Un desafío para los interesados
Publicado por: ghastlyX en 14 Septiembre 2011, 11:31 am
En efecto, la solución que esperaba era la recursiva, pongo aquí la solución que había hecho yo:
Código
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. void rec() {
  5.    char c;
  6.    if (cin >> c) {
  7.        rec();
  8.        cout << c;
  9.    }
  10. }
  11.  
  12. int main() {
  13.    rec();
  14.    cout << endl;
  15. }

Respecto a lo que se comentaba de la pila, aguanta perfectamente 100 llamadas recursivas (y bastantes más):
Código:
alex@portatil:~/codigos$ cat entrada.in
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
alex@portatil:~/codigos$ wc -c entrada.in
102 entrada.in
alex@portatil:~/codigos$ g++ prueba.cc
alex@portatil:~/codigos$ ./a.out < entrada.in
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001


Título: Re: Un desafío para los interesados
Publicado por: Valkyr en 14 Septiembre 2011, 12:49 pm
Si en verdad debe aguantar muchas más de 100 (dependerá también de cada PC) yo recuerdo un método recursivo que implementé para unos ejercicios de grafos y me aguantó una barbaridad de llamadas, pero como eran una barbaridad de datos lo que trabajaba al final petó xD.

Saludos.