Los casos más difíciles de hacer fueron por ejemplo 16 (dieciséis), 21 (veintiuno) que son una única palabra y 1002 (mil dos) que no es “un mil dos” o “uno mil dos”.
Como no chequeo que el resto sea distinto de cero pueden generarse casos como “40 -> cuarenta y cero” o “41 -> cuarenta y cero y uno, cuarenta y cero… y cero y uno” que son quitados con el operador cut (!).
Les dejo acá el código y algunos ejemplos.
17 diecisiete
29 veintinueve
547 quinientos cuarenta y siete
1234 mil doscientos treinta y cuatro
3597426 tres millones quinientos noventa y siete mil cuatrocientos veintiséis
742258963 setecientos cuarenta y dos millones doscientos cincuenta y ocho mil novecientos sesenta y tres
100000000000 cien mil millones
999999999999 novecientos noventa y nueve mil novecientos noventa y nueve millones novecientos noventa y nueve mil novecientos noventa y nueve
1000000000000 un billon
31000 treinta y uno mil*
* Y aquí encontré un bug, debería decir treinta y un mil
Código
% Imprime un numero como texto print_number(N) :- numero(N, L, []), !, atomic_list_concat(L, ' ', A), writeln(A). % Crea una lista [0..N] create_list(N, L) :- findall(X, between(0, N, X), L). % Imprime los numeros entre 0 y N print_numbers(N) :- create_list(N, L), print_aux(L). print_aux([]). print_aux([X|L]) :- print_number(X), print_aux(L). % Convierte un numero en una lista de palabras % ej: numero(132, L, []) -> [ciento, treinta, y, dos]. numero(0) --> [cero]. numero(1) --> [uno]. numero(2) --> [dos]. numero(3) --> [tres]. numero(4) --> [cuatro]. numero(5) --> [cinco]. numero(6) --> [seis]. numero(7) --> [siete]. numero(8) --> [ocho]. numero(9) --> [nueve]. numero(10) --> [dies]. numero(11) --> [once]. numero(12) --> [doce]. numero(13) --> [trece]. numero(14) --> [catorce]. numero(15) --> [quince]. numero(20) --> [veinte]. numero(30) --> [treinta]. numero(40) --> [cuarenta]. numero(50) --> [cincuenta]. numero(60) --> [sesenta]. numero(70) --> [setenta]. numero(80) --> [ochenta]. numero(90) --> [noventa]. numero(100) --> [cien]. % Convertir numeros entre 16 y 19 numero(N) --> {N > 15, N < 20, U is N mod 10, numero(U, X, []), atomic_list_concat([dieci|X], S)}, [S]. % Convertir numeros entre 21 y 29 numero(N) --> {N > 20, N < 30, U is N mod 10, numero(U, X, []), atomic_list_concat([veinti|X], S)}, [S]. % Convertir numeros entre 31 y 99 numero(N) --> {N > 30, N < 100, D is N - (N mod 10), U is N mod 10}, numero(D), [y], numero(U). numero(200) --> [doscientos]. numero(300) --> [trescientos]. numero(400) --> [cuatrocientos]. numero(500) --> [quinientos]. numero(600) --> [seiscientos]. numero(700) --> [setecientos]. numero(800) --> [ochocientos]. numero(900) --> [novecientos]. numero(1000) --> [mil]. % Convertir numeros entre 101 y 199 numero(N) --> {N > 100, N < 200, D is N mod 100}, [ciento], numero(D). % Convertir numeros entre 201 y 999 numero(N) --> {N > 200, N < 1000, C is N - (N mod 100), D is N mod 100}, numero(C), numero(D). % Convertir numeros entre 1001 y 1999 numero(N) --> {N > 1000, N < 2000, D is N mod 1000}, [mil], numero(D). % Convertir numeros entre 2000 y 999 000 que terminan en 000, ej: 7000 numero(N) --> {N >= 2000, N =< 999000, C is N div 1000, D is N mod 1000, D = 0}, numero(C), [mil]. % Convertir numeros entre 2001 y 999 999 numero(N) --> {N > 2000, N < 1000000, C is N div 1000, D is N mod 1000}, numero(C), [mil], numero(D). numero(1000000) --> [un, millon]. % Convertir numeros entre 1 000 001 y 1 999 999 numero(N) --> {N > 1000000, N < 2000000, D is N mod 1000000}, [un, millon], numero(D). % Convertir numeros entre 2 000 000 y 999 999 000 000 que terminan en 000 000, ej: 7 000 000 numero(N) --> {N >= 2000000, N =< 999999000000, C is N div 1000000, D is N mod 1000000, D = 0}, numero(C), [millones]. % Convertir numeros entre 2000001 y 999 999 999 999 numero(N) --> {N > 2000000, N < 1000000000000, C is N div 1000000, D is N mod 1000000}, numero(C), [millones], numero(D). numero(1000000000000) --> [un, billon].
Para ejecutar instalan SWI-Prolog
Guardan el código como “numtext.pl”
Abren cmd en el directorio donde guardaron el archivo
> swipl numtext.pl
?- print_number(N). # donde N es el número a mostrar