Jump to content


Photo

Pasaje de números a letras

números letras conversión

  • Please log in to reply
44 replies to this topic

#41 Dragonlair

Dragonlair

    Newbie

  • Miembros
  • Pip
  • 7 posts
  • LocationMéxico

Posted 10 July 2015 - 10:10 PM

Si lo escribiste con Lazarus, en las opciones de compilación tienes esa configuración estilo "C".
post-12294-0-68771700-1436556747.jpg
 
Estás en lo cierto, trabajo analizando los caracteres numéricos uno a uno y recursivamente en grupos.

Este es el código:


delphi
  1. unit Literales;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, SysUtils, StrUtils;
  7.  
  8. function ToLiteral(N: String): String;
  9.  
  10. implementation
  11.  
  12. function ToLiteral(N: String): String;
  13. function Numeros(N: String): String;
  14. const
  15. suf: array[0..7]of string=('e','i','ta y ','ta','','to ','ientos ','ientos ');
  16. uni: array[0..19]of string=('','uno','dos','tres','cuatro','cinco','seis','siete','ocho','nueve',
  17. 'diez','once','doce','trece','catorce','quince','dieciseis','diecisite','dieciocho','diecinueve');
  18. dec: array[2..9]of string=('veint','trein','cuaren','cincuen','sesen','seten','ochen','noven');
  19. cen: array[1..9]of string=('cien','dosc','tresc','cuatroc','quin','seisc','setec','ochoc','noevec');
  20. var
  21. tm: String;
  22. i: integer;
  23. begin
  24. for i:= 1 to Length(N) do
  25. begin
  26. tm:= Numeros(copy(N, i, 3*WORD((i>3)and(i<5))+6*WORD(i>6))); // se copian 0, 3 ó 6 caracteres
  27. if i = 1 then // Unidades
  28. Result:= uni[ord(N[i])-48]
  29. else if (i = 2) and (N[i] = '1') then // Decenas
  30. Result:= uni[ord(N[1])-38]
  31. else if (i = 2) and (N[i] > '1') then
  32. Result:=dec[ord(N[i])-48]+suf[WORD((N[i]='2')and(N[i-1]>'0'))+2*WORD(N[i]>'2')+WORD((N[i]>'2')
  33. and(N[i-1]='0'))]+Result
  34. else if (i = 3) and(N[i] >= '1')then // Centenas
  35. Result:= cen[ord(N[i])-48]+suf[3+WORD(N[i]='1')+WORD((N[i]='1')and(N[i-1]>'0')or(N[i-2]>'0'))+
  36. 3*WORD(N[i]>'1')]+Result
  37. else if (i = 4) and (tm = 'uno') then // Millares
  38. Result:= 'mil ' + Result
  39. else if (i = 4) and (tm <> '') then
  40. Result:= tm + ' mil ' + Result
  41. else if (i = 7) and (N[i] = '1') then //Millones
  42. Result:= 'un millón ' + Result
  43. else if (i = 7) and (tm <> '') then
  44. Result:= tm + ' millones ' + Result
  45. else if (i = 13) and (N[i] = '1') then //Billones
  46. Result:= 'un billón ' + Result
  47. else if (i = 13) and (tm <> '') then
  48. Result:= tm + ' billones ' + Result
  49. else if (i = 19) and (N[i] = '1') then //Trillones
  50. Result:= 'un trillón ' + Result
  51. else if (i = 19) and (tm <> '') then
  52. Result:= tm + ' trillones ' + Result;
  53. end;
  54. Result:= Trim(Result);
  55. end;
  56. begin
  57. Result:= Numeros(ReverseString(N));
  58. if Result = '' then Result:= 'cero';
  59. end;
  60.  
  61. end.

Saludos.

 

 

Efectivamente lo escribí en Lazarus y con esas directivas.


  • 1

#42 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 11 July 2015 - 10:43 AM

Pues encontré un bug en mi código que debo corregir y con ello aprovecho para recortarlo a 54 líneas:
 


delphi
  1. unit Literales;
  2.  
  3. interface
  4.  
  5. uses
  6. Windows, SysUtils, StrUtils;
  7.  
  8. function ToLiteral(N: String): String;
  9.  
  10. implementation
  11.  
  12. function ToLiteral(N: String): String;
  13. function Numeros(N: String): String;
  14. const
  15. suf: array[0..7]of string=('e','i','ta y ','ta','','to ','ientos ','ientos ');
  16. uni: array[0..19]of string=('','uno','dos','tres','cuatro','cinco','seis','siete','ocho','nueve',
  17. 'diez','once','doce','trece','catorce','quince','dieciseis','diecisite','dieciocho','diecinueve');
  18. dec: array[2..9]of string=('veint','trein','cuaren','cincuen','sesen','seten','ochen','noven');
  19. cen: array[1..9]of string=('cien','dosc','tresc','cuatroc','quin','seisc','setec','ochoc','noevec');
  20. mil: array[0..7]of string=(' mi',' tri',' cuari',' quinti',' sexti',' septi', ' octi',' noni');
  21. var
  22. tm: String;
  23. i: integer;
  24. begin
  25. for i:= 1 to Length(N) do
  26. begin
  27. tm:= Numeros(copy(N, i, 3*WORD((i>3)and(i<5))+6*WORD(i>6))); // se copian 0, 3 ó 6 caracteres
  28. if i = 1 then // Unidades
  29. Result:= uni[ord(N[i])-48]
  30. else if (i = 2) and (N[i] = '1') then // Decenas
  31. Result:= uni[ord(N[1])-38]
  32. else if (i = 2) and (N[i] > '1') then
  33. Result:=dec[ord(N[i])-48]+suf[WORD((N[i]='2')and(N[i-1]>'0'))+2*WORD(N[i]>'2')+WORD((N[i]>'2')
  34. and(N[i-1]='0'))]+Result
  35. else if (i = 3) and(N[i] >= '1')then // Centenas
  36. Result:= cen[ord(N[i])-48]+suf[3+WORD(N[i]='1')+WORD((N[i]='1')and(N[i-1]>'0')or(N[i-2]>'0'))+
  37. 3*WORD(N[i]>'1')]+Result
  38. else if (i = 4) and (tm = 'uno') then // Millares
  39. Result:= 'mil ' + Result
  40. else if (i = 4) and (tm <> '') then
  41. Result:= tm + ' mil ' + Result
  42. else if (i>6) and (((i-1) mod 6) = 0) and (tm = 'uno') then
  43. Result:= 'un' + mil[(i-7) div 6] + 'llón ' + Result
  44. else if (i>6) and (((i-1) mod 6) = 0) and (tm <> '') then
  45. Result:= tm + mil[(i-7) div 6] + 'llones ' + Result;
  46. end;
  47. Result:= Trim(Result);
  48. end;
  49. begin
  50. Result:= Numeros(ReverseString(N));
  51. if Result = '' then Result:= 'cero';
  52. end;
  53.  
  54. end.

Como mi amigo cram llegó a los nonillones, aprovecho para implementar hasta ese número y recortarlo. Se podría recortar otras cuatro líneas más, pero me da un poco de pereza. |-)

 

 

Saludos.


  • 1

#43 cram

cram

    Advanced Member

  • Miembro Platino
  • PipPipPip
  • 832 posts
  • LocationMisiones, Argentina

Posted 11 July 2015 - 11:20 AM

Muy interesante solución Escafandra. Y bueno que hayas detectado el bug.

 

Nunca me gustaron las soluciones usando fuerza bruta, siempre es bueno desmenuzar el problema primero y hallar una solución elegante.

El tema de la recursividad no es para los que andan en pañales y bien utilizado puede sorprender, como en el caso del imbatible QuickSort.

Hace poco intenté solucionar un problema usando recursividad, pero con lo que tengo en mente más interrupciones, ya es suficiente y lo dejé.

 

Respecto del código de Dragonlair, quiero decir algo: No sabía que Lazarus podía interpretar semejantes sentencias, parece híbrido no pascal. En verdad me sorprendió.

 

Creo que el desafío puede darse por más que resuelto.  :ap:  Lo marcaré como resuelto si puedo. Y si luego alguien se prende bueno.

Al final mi código fue el más extenso. Aun así, pienso utilizarlo ya que comprendo su "lógica" (lógicamente). :smiley:

Saludos


  • 1

#44 leobidi

leobidi

    Newbie

  • Miembros
  • Pip
  • 1 posts

Posted 27 July 2018 - 02:02 PM

Buenas a todos, como nuevo en este foro encontre este post de hace un tiempo y me sirvio mucho el codigo de escafandra por cierto, muchas gracias a ti y a todos los participantes de este reto.

 

Comento sin embargo que al menos en mi pais ( URUGUAY ) , por ej. la cantidad 61241, se diria

 

sesenta y un mil doscientos cuarenta y uno, vean la sutil diferencia con el numero 1.. que dependiendo si es ultimo digito o no, su valor en letras

cambia entre UNO y UN.

 

estoy "tratando" de entender mejor dicho codigo y mejorarlo para interpretar el numero 1.

 

saludos.


  • 0

#45 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4111 posts
  • LocationMadrid - España

Posted 31 July 2018 - 04:59 PM

Comento sin embargo que al menos en mi pais ( URUGUAY ) , por ej. la cantidad 61241, se diria
 
sesenta y un mil doscientos cuarenta y uno, vean la sutil diferencia con el numero 1.. que dependiendo si es ultimo digito o no, su valor en letras
cambia entre UNO y UN.


Bienvenido al foro, leobidi.

Una rápida adaptación puede ser esta:


delphi
  1. unit Literales;
  2. // 61001 se lee sesenta y un mil uno
  3. // La versión previa leía sesenta y uno mil uno
  4.  
  5.  
  6. interface
  7.  
  8. uses
  9. Windows, SysUtils, StrUtils;
  10.  
  11. function ToLiteral(N: String): String;
  12.  
  13. implementation
  14.  
  15. function ToLiteral(N: String): String;
  16. function Numeros(N: String): String;
  17. const
  18. suf: array[0..7]of string=('e','i','ta y ','ta','','to ','ientos ','ientos ');
  19. uni: array[0..19]of string=('','un','dos','tres','cuatro','cinco','seis','siete','ocho','nueve',
  20. 'diez','once','doce','trece','catorce','quince','dieciseis','diecisite','dieciocho','diecinueve');
  21. dec: array[2..9]of string=('veint','trein','cuaren','cincuen','sesen','seten','ochen','noven');
  22. cen: array[1..9]of string=('cien','dosc','tresc','cuatroc','quin','seisc','setec','ochoc','noevec');
  23. mil: array[0..7]of string=(' mi',' tri',' cuari',' quinti',' sexti',' septi', ' octi',' noni');
  24. var
  25. tm: String;
  26. i: integer;
  27. begin
  28. for i:= 1 to Length(N) do
  29. begin
  30. tm:= Numeros(copy(N, i, 3*WORD((i>3)and(i<5))+6*WORD(i>6))); // se copian 0, 3 ó 6 caracteres
  31. if i = 1 then // Unidades
  32. Result:= uni[ord(N[i])-48]
  33. else if (i = 2) and (N[i] = '1') then // Decenas
  34. Result:= uni[ord(N[1])-38]
  35. else if (i = 2) and (N[i] > '1') then
  36. Result:=dec[ord(N[i])-48]+suf[WORD((N[i]='2')and(N[i-1]>'0'))+2*WORD(N[i]>'2')+WORD((N[i]>'2')
  37. and(N[i-1]='0'))]+Result
  38. else if (i = 3) and(N[i] >= '1')then // Centenas
  39. Result:= cen[ord(N[i])-48]+suf[3+WORD(N[i]='1')+WORD((N[i]='1')and(N[i-1]>'0')or(N[i-2]>'0'))+
  40. 3*WORD(N[i]>'1')]+Result
  41. else if (i = 4) and (tm = 'un') then // Millares
  42. Result:= 'mil ' + Result
  43. else if (i = 4) and (tm <> '') then
  44. Result:= tm + ' mil ' + Result
  45. else if (i>6) and (((i-1) mod 6) = 0) and (tm = 'un') then
  46. Result:= 'un' + mil[(i-7) div 6] + 'llón ' + Result
  47. else if (i>6) and (((i-1) mod 6) = 0) and (tm <> '') then
  48. Result:= tm + mil[(i-7) div 6] + 'llones ' + Result;
  49. end;
  50. // Result:= Trim(Result);
  51. end;
  52. begin
  53. Result:= Numeros(ReverseString(N));
  54. if Result = '' then Result:= 'cero';
  55. if Result[Length(Result)-1] = 'u' then Result:= Result + 'o';
  56. end;
  57.  
  58. end.

Saludos.


  • 0




IP.Board spam blocked by CleanTalk.