NumeracionRomana.vb

  1. ' NumeracionRomana.vb — ProInf.net — 26-feb-2012
  2. '
  3. ' Convierte un número a numeración romana
  4. ' superando la barrera de 3999 mediante los paréntesis
  5. ' que multiplican por mil
  6.  
  7. Public NotInheritable Class NumeracionRomana
  8.  
  9. Public Const MINIMO_ROMANO As Integer = 1
  10. Public Const MAXIMO_ROMANO_SIN_PARENTESIS As Integer = 3999
  11.  
  12. ' Los paréntesis multiplican por mil
  13. '
  14. ' Ejemplos:
  15. ' 3572 = MMMDLXXII
  16. ' 3999 = MMMCMXCIX
  17. ' 4000 = M(V)
  18. ' 14285 = (X)M(V)CCLXXXV
  19. ' 17856 = (XV)MMDCCCLVI
  20. ' 46424 = (XLV)MCDXXIV
  21. ' 99989 = (XC)M(X)CMLXXXIX
  22. '
  23. Public Shared Function Obtener(ByVal numero As Integer) As String
  24. If numero < MINIMO_ROMANO Then Return ""
  25.  
  26. Dim resultado As New System.Text.StringBuilder()
  27. Dim potencia10 As Integer = 0
  28.  
  29. Do While numero > 0
  30. Dim digitoDecimal = numero Mod 10
  31. numero \= 10
  32. Dim numeroRomano = ConvertirUnidades(digitoDecimal)
  33.  
  34. If potencia10 > 0 Then
  35. Dim trio() As String = ObtenerTrioRomano(potencia10)
  36. numeroRomano = ReemplazarCifrasRomanas(numeroRomano, trio)
  37. End If
  38. potencia10 += 1
  39.  
  40. resultado.Insert(0, numeroRomano)
  41. Loop
  42. Return ReducirParentesis(resultado.ToString())
  43. End Function
  44.  
  45. Private Shared Function ObtenerTrioRomano(ByVal potencia10 As Integer) As String()
  46. 'potencia10: 0,1,2,3,4,5,6,7,8,...
  47. Dim triosRomanos() = {"IVX", "XLC", "CDM", "MVX"}
  48. Dim indiceTrio = ((potencia10 - 1) Mod 3) + 1 '0, 1,2,3, 1,2,3, 1,2,3, ...
  49. Dim numeroParentesis = (potencia10 - 1) \ 3 '0, 0,0,0, 1,1,1, 2,2,2, 3,3,3, ...
  50. Dim trio = triosRomanos(indiceTrio)
  51. Dim resultado(2) As String
  52.  
  53. resultado(0) = AgregarParentesis(trio(0), numeroParentesis)
  54. If indiceTrio = 3 Then numeroParentesis += 1
  55. resultado(1) = AgregarParentesis(trio(1), numeroParentesis)
  56. resultado(2) = AgregarParentesis(trio(2), numeroParentesis)
  57.  
  58. 'IVX, XLC, CDM, M(VX), (XLC), (CDM), (M(VX)), ((XLC)), ((CDM)), ((M(VX))), ...
  59. Return resultado
  60. End Function
  61.  
  62. Private Shared Function ReemplazarCifrasRomanas(
  63. ByVal numeroRomano As String, ByVal trio() As String
  64. ) As String
  65. Return numeroRomano.
  66. Replace("X", trio(2)).
  67. Replace("V", trio(1)).
  68. Replace("I", trio(0))
  69. End Function
  70.  
  71. Public Shared Function ConvertirUnidades(ByVal cifras As Integer) As String
  72. Dim numerosRomanos = {"I", "II", "III", "IV", "V", "VI", "VII",
  73. "VIII", "IX", "X", "XI", "XII", "XIII"}
  74. If cifras >= 1 And cifras <= 13 Then
  75. Return numerosRomanos(cifras - 1)
  76. Else
  77. Return ""
  78. End If
  79. End Function
  80.  
  81. Private Shared Function AgregarParentesis(
  82. ByVal texto As String, ByVal numero As Integer
  83. ) As String
  84. If numero >= 1 Then
  85. Return StrDup(numero, "(") & texto & StrDup(numero, ")")
  86. Else
  87. Return texto
  88. End If
  89. End Function
  90.  
  91. Private Shared Function ReducirParentesis(ByVal texto As String) As String
  92. Do While texto.Contains(")(")
  93. texto = texto.Replace(")(", "")
  94. Loop
  95. Return texto
  96. End Function
  97.  
  98. End Class
  99.  

Proinf.net