Hace un par de días (aquí) escribí sobre un programa que transforma una cifra en números a letras.La idea es que ponía una cifra: 2347, por ejemplo, y el programa debía darme como resultado "dos mil trescientos cuarenta y siete pesos". Puse en el artículo mencionado mi primera solución en Prolog, pero he aquí que un avezado lector, buen programador, mejor amigo y técnicamente infalible, Ernesto Blum, me dijo que no estaba considerando algunos casos.
Hoy que fui a dar mi clase, expuse el código fuente y al irlo escribiendo en el pizarrón hallé que algo andaba mal. Así pues, decidí que al llegar a casa re-escribiría el problema para darle una solución definitiva. En un rato hallé las dificultades y según yo, ya las resolví. He aquí mi código fuente:
/********************************************/
/* Programa que traduce de números a letras */
/* Versión 1.1 */
/* 18 mayo 2011 */
/* Programó: La Morsa */
/********************************************/
predicatesCabe señalar que el programa está escrito en Turbo Prolog 2.0 y que se está usando el tamaño de variable entera para el procesamiento de la cifra, por ende, solamente puede resolver el problema para números enteros mayores a cero y menores a 32768, que es el límite de un entero. Entre otras cosas, este código ya me dejó más contento porque solamente contiene una salida de la función recursiva y eso me parece más "elegante", valga la expresión.
equiv(integer,symbol)
pasa_num_a_letras(integer)
clauses
equiv(1,un).
equiv(2,dos).
equiv(3,tres).
equiv(4,cuatro).
equiv(5,cinco).
equiv(6,seis).
equiv(7,siete).
equiv(8,ocho).
equiv(9,nueve).
equiv(10,diez).
equiv(11,once).
equiv(12,doce).
equiv(13,trece).
equiv(14,catorce).
equiv(15,quince).
equiv(16,dieciseis).
equiv(17,diecisiete).
equiv(18,dieciocho).
equiv(19,diecinueve).
equiv(20,veinte).
equiv(21,veintiuno).
equiv(22,veintidos).
equiv(23,veintitres).
equiv(24,veinticuatro).
equiv(25,veinticinco).
equiv(26,veintiseis).
equiv(27,veintisiete).
equiv(28,veintiocho).
equiv(29,veintinueve).
equiv(30,treinta).
equiv(40,cuarenta).
equiv(50,cincuenta).
equiv(60,sesenta).
equiv(70,setenta).
equiv(80,ochenta).
equiv(90,noventa).
equiv(100,ciento).
equiv(200,doscientos).
equiv(300,trescientos).
equiv(400,cuatrocientos).
equiv(500,quinientos).
equiv(600,seiscientos).
equiv(700,setecientos).
equiv(800,ochocientos).
equiv(900,novecientos).
equiv(1000,mil).
pasa_num_a_letras(X) :- /* condicion terminales */
X < 30,
equiv(X,Resultado),
write(Resultado).
/* predicados recursivos */
pasa_num_a_letras(Cifra) :-
Cifra div 1000 <> 0, /* la cifra tiene diez miles */
DMiles = Cifra div 1000,
DMiles > 30,
pasa_num_a_letras(DMiles), /*doble recursion */
write(" mil "),
Miles = Cifra - (DMiles * 1000),
pasa_num_a_letras(Miles).
pasa_num_a_letras(Cifra) :-
Cifra div 1000 <> 0, /* la cifra tiene miles */
Miles = Cifra div 1000,
equiv(Miles,Resultado),
write(Resultado, " mil "),
Cientos = Cifra - (Miles * 1000),
pasa_num_a_letras(Cientos).
pasa_num_a_letras(Cifra) :-
Cifra div 100 <> 0, /* la cifra tiene cientos */
Cien = Cifra div 100,
Cien1 = Cien * 100,
equiv(Cien1,Resultado),
write(Resultado," "),
Decenas = Cifra - (Cien * 100),
pasa_num_a_letras(Decenas).
pasa_num_a_letras(Cifra) :-
Cifra div 10 <> 0, /* la cifra tiene decenas */
Dec = Cifra div 10,
Dec1 = Dec * 10,
equiv(Dec1,Resultado),
write(Resultado," y "),
Unidades = Cifra - (Dec * 10),
pasa_num_a_letras(Unidades).
Igualmente, expresiones como:
Cientos = Cifra - (Miles * 1000),
Podrían ponerse como
Cientos = Cifra mod 1000
Hice algunas pruebas y parece que ahora sí todo funciona bien.
A todo esto, el mismo Ernesto Blum me mandó la solución de este programa en el lenguaje de programación Ruby:
#!/usr/bin/ruby
def cen_out(numero)
uni = numero % 10 / 1
dec = numero % 100 / 10
cen = numero % 1000 / 100
case cen
when 0; return ""
when 1; if uni == 0 && dec == 0
return "cien"
else
return "ciento "
end
when 2; return "doscientos "
when 3; return "trescientos "
when 4; return "cuatrocientos "
when 5; return "quinientos "
when 6; return "seiscientos "
when 7; return "setecientos "
when 8; return "ochocientos "
when 9; return "novecientos "
end
end
def dec_out(numero)
uni = numero % 10 / 1
dec = numero % 100 / 10
if dec == 1
case uni
when 0; return "diez"
when 1; return "once"
when 2; return "doce"
when 3; return "trece"
when 4; return "catorce"
when 5; return "quince"
when 6; return "dieciseis"
when 7; return "diecisiete"
when 8; return "dieciocho"
when 9; return "diecinueve"
end
elsif uni == 0
case dec
when 0; return ""
when 1; return ""
when 2; return "veinte"
when 3; return "treinta"
when 4; return "cuarenta"
when 5; return "cincuenta"
when 6; return "sesenta"
when 7; return "setenta"
when 8; return "ochenta"
when 9; return "noventa"
end
else
case dec
when 0; return ""
when 1; return ""
when 2; return "veinti"
when 3; return "treinta y "
when 4; return "cuarenta y "
when 5; return "cincuenta y "
when 6; return "sesenta y "
when 7; return "setenta y "
when 8; return "ochenta y "
when 9; return "noventa y "
end
end
end
def uni_out(numero)
uni = numero % 10 / 1
dec = numero % 100 / 10
if dec == 1
return ""
else
case uni
when 0; return ""
when 1; return "un"
when 2; return "dos"
when 3; return "tres"
when 4; return "cuatro"
when 5; return "cinco"
when 6; return "seis"
when 7; return "siete"
when 8; return "ocho"
when 9; return "nueve"
end
end
end
def letra(numero)
return cen_out(numero), dec_out(numero), uni_out(numero), "\n"
end
for n in 1..1000
print letra(n)
end
Por el momento así las cosas. Cualquier cambio o problema con el código mío, lo pondré en el blog en su oportunidad.
Tidak ada komentar:
Posting Komentar