Convertir números en romano

Enviado por felipelvrd el 5 Junio, 2011 - 01:07.

Tengo como un mes de ser blogger y hasta ahora hago mi primera entrada mrgreen

Bueno, estoy aprendiendo a programar en c++, en la universidad, voy a terminar mi primer semestre first .

Y como mi primer programa hice una aplicación de terminal que convierte un numero del 1 al 3999 en romano, entonces lo publico, para el que lo quiera usar.

http://www.mediafire.com/?dop51b41d6b8bh8

Imagen de MOSE
Enviado por MOSE el 5 Junio, 2011 - 02:24.

Obviando el hecho de que un convertidor de tiempo shinigami a humano habría sido más útil. mrgreen

Qué persona con dos dedos de frente se bajaría y ejecutaría un archivo binario así sin ningún tipo de garantía. dumb
No sé ni el motivo por el cuál no pones directamente el código fuente (porque supongo que no pretenderás vender los derechos que tengas sobre este complicadísimo programa). tiko

Imagen de julio-linux
Enviado por julio-linux el 5 Junio, 2011 - 15:26.
MOSE escribió:

Obviando el hecho de que un convertidor de tiempo shinigami a humano habría sido más útil. mrgreen

Qué persona con dos dedos de frente se bajaría y ejecutaría un archivo binario así sin ningún tipo de garantía. dumb
No sé ni el motivo por el cuál no pones directamente el código fuente (porque supongo que no pretenderás vender los derechos que tengas sobre este complicadísimo programa). tiko

meparto meparto meparto Totalmente de acuerdo

Imagen de blaw
Enviado por blaw el 5 Junio, 2011 - 21:48.
MOSE escribió:

...

Entiendo un poco tu comentario, pero tampoco es para que lo que el intento hacer (que la forma de querer compartirlo no es la correcta) lo menosprecies con aires de pedantes, en dado caso si su trabajo te parece cosa de medio pelo pues asómbranos tu, elaborando el convertidor de tiempo shinigami a humano que mencionas.

Imagen de MOSE
Enviado por MOSE el 5 Junio, 2011 - 22:23.
blaw escribió:
MOSE escribió:

...

Entiendo un poco tu comentario, pero tampoco es para que lo que el intento hacer (que la forma de querer compartirlo no es la correcta) lo menosprecies con aires de pedantes, en dado caso si su trabajo te parece cosa de medio pelo pues asómbranos tu, elaborando el convertidor de tiempo shinigami a humano que mencionas.

Pues me parece que no lo entendiste en el contexto correcto, ya que no tengo afán de menospreciar a nadie (y menos a felipelvrd, porque su avatar me gusta mucho :) ), el tono era extremadamente jocoso (supongo que no puse suficientes smileys, aunque creía que quedaría claro con lo del convertidor de tiempo, ya que se dice que el autor del manga se inventaba los números).

Lo único que iba un poco en serio era lo de que nadie ejecutaría un binario que no sabe de dónde ha salido.

Imagen de MOSE
Enviado por MOSE el 5 Junio, 2011 - 23:27.

No es un convertidor de tiempo shinigami a humano pero creo que con algo así habría valido.

/*Convierte numeros en base decimal en el intervalo [1, 3999] a numeros romanos*/

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

char *toroman(long lnum, char *sroman_num);

int main(int argc, char **argv)
{
long lnum;
char *remainder;
char sroman_num[20] = "";

if (argc != 2)
{
fprintf(stderr, "Uso:\n"
"%s num (en el intervalo [1, 3999])\n", argv[0]);
return 1;
}

lnum = strtol(argv[1], &remainder, 10);
if (*remainder != '\0' || lnum < 1 || lnum > 3999)
{
fprintf(stderr, "\"%s\" no es un número entero en el intervalo"
" [1, 3999]\n", argv[1]);
return 1;
}
printf("%s=> %s\n", argv[1], toroman(lnum, sroman_num));
return 0;
}

char *toroman(long lnum, char *sroman_num)
{
short i;

for (i = 0; i < lnum / 1000; i++)
strcat(sroman_num, "M");
switch ((lnum / 100) % 10)
{
case 4:
strcat(sroman_num, "CD");
break;
case 9:
strcat(sroman_num, "CM");
break;
default:
if ((lnum / 100) % 10 > 4)
{
strcat(sroman_num, "D");
lnum -= 500;
}
for (i = 0; i < (lnum / 100) % 10; i++)
strcat(sroman_num, "C");
break;
}

switch ((lnum / 10) % 10)
{
case 4:
strcat(sroman_num, "XL");
break;
case 9:
strcat(sroman_num, "XC");
break;
default:
if ((lnum / 10) % 10 > 4)
{
strcat(sroman_num, "L");
lnum -= 50;
}
for (i = 0; i < (lnum / 10) % 10; i++)
strcat(sroman_num, "X");
break;
}

switch (lnum % 10)
{
case 4:
strcat(sroman_num, "IV");
break;
case 9:
strcat(sroman_num, "IX");
break;
default:
if (lnum % 10 > 4)
{
strcat(sroman_num, "V");
lnum -= 5;
}
for (i = 0; i < lnum % 10; i++)
strcat(sroman_num, "I");
break;
}
return sroman_num;
}
Imagen de felipelvrd
Enviado por felipelvrd el 6 Junio, 2011 - 01:42.
MOSE escribió:

[...]

Lo compile y no me funciono, le terminal devolvió esto:

felipe@debian:~/Escritorio$ ./romanos.bin
Uso:
./romanos.bin num (en el intervalo [1, 3999])
felipe@debian:~/Escritorio$

Bueno aquí esta el código fuente del mio:

#include <iostream>
#include <cstdio>
using namespace std;
int main(int argc, char *argv[]) {
int x;
x=4000;
while((x>3999) || (x<1))
{
printf("Escriba un numero del 1 al 3999: ");
scanf("%d",&x);
}
printf("%d",x);
printf(" en números romanos es: ");
if(x>=3000)
{
printf("MMM");
x=x-3000;
}
else
{
if(x>=2000)
{
printf("MM");
x=x-2000;
}
else
{
if(x>=1000)
{
printf("M");
x=x-1000;
}
else
{
}
}
}
if(x>=900)
{
printf("CM");
x=x-900;
}
else
{
if(x>=800)
{
printf("DCCC");
x=x-800;
}
else
{
if(x>=700)
{
printf("DCC");
x=x-700;
}
else
{
if(x>=600)
{
printf("DC");
x=x-600;
}
else
{
if(x>=500)
{
printf("D");
x=x-500;
}
else
{
if(x>=400)
{
printf("CD");
x=x-400;
}
else
{
if(x>=300)
{
printf("CCC");
x=x-300;
}
else
{
if(x>=200)
{
printf("CC");
x=x-200;
}
else
{
if(x>=100)
{
printf("C");
x=x-100;
}
else
{
}
}
}
}
}
}
}
}
}
if(x>=90)
{
printf("XC");
x=x-90;
}
else
{
if(x>=80)
{
printf("LXXX");
x=x-80;
}
else
{
if(x>=70)
{
printf("LXX");
x=x-70;
}
else
{
if(x>=60)
{
printf("LX");
x=x-60;
}
else
{
if(x>=50)
{
printf("L");
x=x-50;
}
else
{
if(x>=40)
{
printf("XL");
x=x-40;
}
else
{
if(x>=30)
{
printf("XXX");
x=x-30;
}
else
{
if(x>=20)
{
printf("XX");
x=x-20;
}
else
{
if(x>=10)
{
printf("X");
x=x-10;
}
else
{
}
}
}
}
}
}
}
}
}

if(x==0)
{
}
else
{
if(x==9)
{
printf("IX");
}
else
{
if(x==8)
{
printf("VIII");
}
else
{
if(x==7)
{
printf("VII");
}
else
{
if(x==6)
{
printf("VI");
}
else
{
if(x==5)
{
printf("V");
}
else
{
if(x==4)
{
printf("IV");
}
else
{
if(x==3)
{
printf("III");
}
else
{
if(x==2)
{
printf("II");
}
else
{
printf("I");
}
}
}
}
}
}
}
}
}
printf("\n");
return 0;
}

Imagen de MOSE
Enviado por MOSE el 6 Junio, 2011 - 06:53.
felipelvrd escribió:
MOSE escribió:

[...]

Lo compile y no me funciono, le terminal devolvió esto:


felipe@debian:~/Escritorio$ ./romanos.bin
Uso:
./romanos.bin num (en el intervalo [1, 3999])
felipe@debian:~/Escritorio$

Tienes que pasarle el número como argumento. (Al menos eso quería que dijese el mensaje, no sé si se habrá entendido).

Imagen de darkshadow
Enviado por darkshadow el 6 Junio, 2011 - 19:08.

Pues tu codigo.. funciona pero no has pensado en hacerlo con divisiones sucesivas ? y todo eso con un contador dentro de un while? el codigo seria un poco mas complicado pero fuera mas corto... te lo dejo por si te entra la curiosidad... vere si en la noche pongo mi version de esta forma, como te digo, aun asi me parece muy bueno tengo muchos compañers que no lograran hacer eso simplemente por pereza. Vamos sigue asi! first

Imagen de jjgomera
Enviado por jjgomera el 6 Junio, 2011 - 20:12.
darkshadow escribió:

Pues tu codigo.. funciona pero no has pensado en hacerlo con divisiones sucesivas ? y todo eso con un contador dentro de un while? el codigo seria un poco mas complicado pero fuera mas corto... te lo dejo por si te entra la curiosidad... vere si en la noche pongo mi version de esta forma, como te digo, aun asi me parece muy bueno tengo muchos compañers que no lograran hacer eso simplemente por pereza. Vamos sigue asi! first

Aplicando esa idea con python:

def Decimal2Romano(numero):
    conversion={1:"I", 4:"IV", 5:"V", 9: "IX", 10:"X", 40:"XL", 50:"L", 90:"XC", 100:"C", 400:"CD", 500:"D", 900:"CM", 1000:"M"}
    resultado=""
    for decimal, romano in sorted(conversion.items(), reverse=True):
        while numero >= decimal:
            numero -= decimal           
            resultado += romano
    return resultado
   
if __name__ == "__main__":
    import sys
    print Decimal2Romano(int(sys.argv[1]))

Por qué me gustará python? mrgreen

jjgomera@ordenata:~/downloads$ python ejemplo.py 3987
MMMCMLXXXVII
Imagen de MOSE
Enviado por MOSE el 6 Junio, 2011 - 20:22.
jjgomera escribió:
darkshadow escribió:

Pues tu codigo.. funciona pero no has pensado en hacerlo con divisiones sucesivas ? y todo eso con un contador dentro de un while? el codigo seria un poco mas complicado pero fuera mas corto... te lo dejo por si te entra la curiosidad... vere si en la noche pongo mi version de esta forma, como te digo, aun asi me parece muy bueno tengo muchos compañers que no lograran hacer eso simplemente por pereza. Vamos sigue asi! first

Aplicando esa idea con python:

def Decimal2Romano(numero):
    conversion={1:"I", 4:"IV", 5:"V", 9: "IX", 10:"X", 40:"XL", 50:"L", 90:"XC", 100:"C", 400:"CD", 500:"D", 900:"CM", 1000:"M"}
    resultado=""
    for decimal, romano in sorted(conversion.items(), reverse=True):
        while numero >= decimal:
            numero -= decimal           
            resultado += romano
    return resultado
   
if __name__ == "__main__":
    import sys
    print Decimal2Romano(int(sys.argv[1]))

Por qué me gustará python? mrgreen

jjgomera@ordenata:~/downloads$ python ejemplo.py 3987
MMMCMLXXXVII

La verdad es que lo hice rápido y a lo guarro, pero la versión en C también puede acortarse bastante más usando un array, y un solo switch dentro de un bucle for.
Aunque la verdad es que con todo y eso, python es bastante más conciso.

EDITO: Me refería a algo así.

char *toroman(long lnum, char *sroman_num)
{
short i, j;
short div = 100;
char *aroman[7] = {"M", "D", "C", "L", "X", "V", "I"};

for (i = 0; i < lnum / 1000; i++)
strcat(sroman_num, "M");
for (i = 0; i < 6; i += 2)
{
switch ((lnum / div) % 10)
{
case 4:
strcat(sroman_num, aroman[i + 2]);
strcat(sroman_num, aroman[i + 1]);
break;
case 9:
strcat(sroman_num, aroman[i + 2]);
strcat(sroman_num, aroman[i]);
break;
default:
if ((lnum / div) % 10 > 4)
{
strcat(sroman_num, aroman[i + 1]);
lnum -= 5 * div;
}
for (j = 0; j < (lnum / div) % 10; j++)
strcat(sroman_num, aroman[i + 2]);
break;
}
div /= 10;
}
return sroman_num;
}