java - para - convertir numeros naturales a romanos c#
Conversión de números enteros a números romanos-Java (22)
Aquí están los resultados de MI tarea. No garantiza que la entrada esté en el rango correcto y probablemente debería usar StringBuilder
(¡la vez que lo busqué!) Y no es un método único. Pero si alguien está leyendo hasta aquí, agradecería su opinión positiva y negativa.
import java.util.Scanner;
/**
*Main() allows user input and tests 1-3999
*toRoman() breaks the number down into digits and passes them to romanLogic()
*romanLogic() converts each digit into a the numerals that represent it.
*/
public class RomanNumerals
{
public static void main(String args[]){
Scanner in = new Scanner(System.in);
System.out.print("give us an integer < 4000: ");
System.out.println("the roman numeral version is: " + toRoman(in.nextInt()));
for (int i = 1; i<=3999; i++){
System.out.println(i +" === "+ toRoman(i));
}
}
public static String toRoman(int i){
String output = "";
int digits = i%10;
int tens = (i%100)/10;
int hundreds = (i%1000)/100;
int thousands = (i%10000)/1000;
return (romanLogic(thousands, "M","","")+
romanLogic(hundreds,"C","D","M")+
romanLogic(tens,"X","L","C")+
romanLogic(digits,"I","V","X"));
}
public static String romanLogic(int i, String ones, String fives, String tens){
String result = "";
if (i == 0){
return result;
} else {
if ((i>=4)&&(i<=8)){
result += fives;
}
if (i==9){
result += tens;
}
if(i%5 < 4){
while(i%5 > 0){
result += ones;
i--;
}
}
if(i%5 == 4){
result = ones + result;
}
}
return result;
}
}
Esta es una tarea con la que estoy teniendo problemas.
Necesito hacer un entero al convertidor de Numeral Romano usando un método. Más tarde, debo usar el programa para escribir 1 a 3999 en números romanos, por lo que la codificación está desactivada. Mi código a continuación es muy escueto; es un bucle de E / S básico con una forma de salir mientras se usa un paquete para getIntegerFromUser
creamos en clase.
¿Hay alguna forma de asignar valores a Strings y luego agregarlos juntos cuando llamo al método?
Actualización: obtuve un pseudo código de mi profesor para ayudarme, y aunque entiendo lo que está tratando de decir, tengo algunos problemas con los if
. ¿Necesitaré muchas, muchas declaraciones if
para que mi convertidor maneje correctamente el formato de números romanos o hay alguna manera en que puedo hacer esto con más eficiencia? Actualicé mi código para reflejar mi método de marcador de posición.
Actualización (28 de octubre de 2012): lo tengo funcionando. Esto es lo que terminé usando:
public static String IntegerToRomanNumeral(int input) {
if (input < 1 || input > 3999)
return "Invalid Roman Number Value";
String s = "";
while (input >= 1000) {
s += "M";
input -= 1000; }
while (input >= 900) {
s += "CM";
input -= 900;
}
while (input >= 500) {
s += "D";
input -= 500;
}
while (input >= 400) {
s += "CD";
input -= 400;
}
while (input >= 100) {
s += "C";
input -= 100;
}
while (input >= 90) {
s += "XC";
input -= 90;
}
while (input >= 50) {
s += "L";
input -= 50;
}
while (input >= 40) {
s += "XL";
input -= 40;
}
while (input >= 10) {
s += "X";
input -= 10;
}
while (input >= 9) {
s += "IX";
input -= 9;
}
while (input >= 5) {
s += "V";
input -= 5;
}
while (input >= 4) {
s += "IV";
input -= 4;
}
while (input >= 1) {
s += "I";
input -= 1;
}
return s;
}
Creo que mi solución es una de las más concisas:
private static String convertToRoman(int mInt) {
String[] rnChars = { "M", "CM", "D", "C", "XC", "L", "X", "IX", "V", "I" };
int[] rnVals = { 1000, 900, 500, 100, 90, 50, 10, 9, 5, 1 };
String retVal = "";
for (int i = 0; i < rnVals.length; i++) {
int numberInPlace = mInt / rnVals[i];
if (numberInPlace == 0) continue;
retVal += numberInPlace == 4 && i > 0? rnChars[i] + rnChars[i - 1]:
new String(new char[numberInPlace]).replace("/0",rnChars[i]);
mInt = mInt % rnVals[i];
}
return retVal;
}
Creo que si estudias cuidadosamente la teoría de los números romanos, no necesitas mapeos para los números 4, 9, 40, etc. porque la teoría nos dice si el número romano es IV = 5-1 = 4, por lo tanto, cuando el prefijo es más pequeño que el número siguiente en ese caso tiene que restar el número anterior del número siguiente para obtener el valor real y esto es lo que he incorporado en mi código para el problema, echar un vistazo y señalar cualquier error si es necesario, seguí este tabla para idear mi lógica - http://literacy.kent.edu/Minigrants/Cinci/romanchart.htm
import java.util.Set;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
import java.io.FileReader;
import java.io.IOException;
import java.io.BufferedReader;
public class RomanStringToIntegerConversion {
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in)));
String[] romanString = br.readLine().split("");
HashMap<String, Integer> romanToIntegerMap = new HashMap<String, Integer>();
romanToIntegerMap.put("I", 1);
romanToIntegerMap.put("V", 5);
romanToIntegerMap.put("X", 10);
romanToIntegerMap.put("L", 50);
romanToIntegerMap.put("C", 100);
romanToIntegerMap.put("D", 500);
romanToIntegerMap.put("M", 1000);
int numLength = romanString.length;
Set<Integer> lessIndices = new HashSet<Integer>();
for(int i = 0; i < numLength; ++i){
if(i+1 < numLength){
if(romanToIntegerMap.get(romanString[i]) < romanToIntegerMap.get(romanString[i+1]))
lessIndices.add(i);
}
}
int num = 0;
for(int i = 0; i < numLength;){
if(!lessIndices.contains(i)){
num = num + romanToIntegerMap.get(romanString[i]);
++i;
}
else{
num = num + romanToIntegerMap.get(romanString[i+1]) - romanToIntegerMap.get(romanString[i]);
i+=2;
}
}
System.out.println("The integer representation of the roman numeral is : " + num);
}
}
Desde el sitio web de Java Notes 6.0 :
/**
* An object of type RomanNumeral is an integer between 1 and 3999. It can
* be constructed either from an integer or from a string that represents
* a Roman numeral in this range. The function toString() will return a
* standardized Roman numeral representation of the number. The function
* toInt() will return the number as a value of type int.
*/
public class RomanNumeral {
private final int num; // The number represented by this Roman numeral.
/* The following arrays are used by the toString() function to construct
the standard Roman numeral representation of the number. For each i,
the number numbers[i] is represented by the corresponding string, letters[i].
*/
private static int[] numbers = { 1000, 900, 500, 400, 100, 90,
50, 40, 10, 9, 5, 4, 1 };
private static String[] letters = { "M", "CM", "D", "CD", "C", "XC",
"L", "XL", "X", "IX", "V", "IV", "I" };
/**
* Constructor. Creates the Roman number with the int value specified
* by the parameter. Throws a NumberFormatException if arabic is
* not in the range 1 to 3999 inclusive.
*/
public RomanNumeral(int arabic) {
if (arabic < 1)
throw new NumberFormatException("Value of RomanNumeral must be positive.");
if (arabic > 3999)
throw new NumberFormatException("Value of RomanNumeral must be 3999 or less.");
num = arabic;
}
/*
* Constructor. Creates the Roman number with the given representation.
* For example, RomanNumeral("xvii") is 17. If the parameter is not a
* legal Roman numeral, a NumberFormatException is thrown. Both upper and
* lower case letters are allowed.
*/
public RomanNumeral(String roman) {
if (roman.length() == 0)
throw new NumberFormatException("An empty string does not define a Roman numeral.");
roman = roman.toUpperCase(); // Convert to upper case letters.
int i = 0; // A position in the string, roman;
int arabic = 0; // Arabic numeral equivalent of the part of the string that has
// been converted so far.
while (i < roman.length()) {
char letter = roman.charAt(i); // Letter at current position in string.
int number = letterToNumber(letter); // Numerical equivalent of letter.
i++; // Move on to next position in the string
if (i == roman.length()) {
// There is no letter in the string following the one we have just processed.
// So just add the number corresponding to the single letter to arabic.
arabic += number;
}
else {
// Look at the next letter in the string. If it has a larger Roman numeral
// equivalent than number, then the two letters are counted together as
// a Roman numeral with value (nextNumber - number).
int nextNumber = letterToNumber(roman.charAt(i));
if (nextNumber > number) {
// Combine the two letters to get one value, and move on to next position in string.
arabic += (nextNumber - number);
i++;
}
else {
// Don''t combine the letters. Just add the value of the one letter onto the number.
arabic += number;
}
}
} // end while
if (arabic > 3999)
throw new NumberFormatException("Roman numeral must have value 3999 or less.");
num = arabic;
} // end constructor
/**
* Find the integer value of letter considered as a Roman numeral. Throws
* NumberFormatException if letter is not a legal Roman numeral. The letter
* must be upper case.
*/
private int letterToNumber(char letter) {
switch (letter) {
case ''I'': return 1;
case ''V'': return 5;
case ''X'': return 10;
case ''L'': return 50;
case ''C'': return 100;
case ''D'': return 500;
case ''M'': return 1000;
default: throw new NumberFormatException(
"Illegal character /"" + letter + "/" in Roman numeral");
}
}
/**
* Return the standard representation of this Roman numeral.
*/
public String toString() {
String roman = ""; // The roman numeral.
int N = num; // N represents the part of num that still has
// to be converted to Roman numeral representation.
for (int i = 0; i < numbers.length; i++) {
while (N >= numbers[i]) {
roman += letters[i];
N -= numbers[i];
}
}
return roman;
}
/**
* Return the value of this Roman numeral as an int.
*/
public int toInt() {
return num;
}
}
Después de ver algunas de las respuestas aquí tuve que publicar esto. Creo que mi algoritmo es mucho más fácil de entender y el poco rendimiento perdido no es importante ni siquiera a una escala relativamente grande. También estoy obedeciendo las convenciones de codificación estandarizadas en oposición a algunos de los usuarios aquí.
Tiempo promedio de conversión: 0.05ms (basado en convertir todos los números 1-3999 y dividir por 3999)
public static String getRomanNumeral(int arabicNumber) {
if (arabicNumber > 0 && arabicNumber < 4000) {
final LinkedHashMap<Integer, String> numberLimits =
new LinkedHashMap<>();
numberLimits.put(1, "I");
numberLimits.put(4, "IV");
numberLimits.put(5, "V");
numberLimits.put(9, "IX");
numberLimits.put(10, "X");
numberLimits.put(40, "XL");
numberLimits.put(50, "L");
numberLimits.put(90, "XC");
numberLimits.put(100, "C");
numberLimits.put(400, "CD");
numberLimits.put(500, "D");
numberLimits.put(900, "CM");
numberLimits.put(1000, "M");
String romanNumeral = "";
while (arabicNumber > 0) {
int highestFound = 0;
for (Map.Entry<Integer, String> current : numberLimits.entrySet()){
if (current.getKey() <= arabicNumber) {
highestFound = current.getKey();
}
}
romanNumeral += numberLimits.get(highestFound);
arabicNumber -= highestFound;
}
return romanNumeral;
} else {
throw new UnsupportedOperationException(arabicNumber
+ " is not a valid Roman numeral.");
}
}
Primero, debe tener en cuenta que los números romanos están solo en el intervalo de <1-4000), pero eso se puede resolver mediante una simple excepción de lanzamiento y lanzamiento. Luego puede tratar de encontrar el número romano más grande en un número entero dado y si lo encuentra restarlo del número original y agregarlo al resultado. Repita con el número recién adquirido hasta que llegue a cero.
En realidad, hay otra forma de ver este problema, no como un problema numérico, sino un problema unario, comenzando con el carácter básico de los números romanos, "yo". Entonces representamos el número solo con I, y luego reemplazamos los caracteres en el valor ascendente de los caracteres romanos.
public String getRomanNumber(int number) {
return join("", nCopies(number, "I"))
.replace("IIIII", "V")
.replace("IIII", "IV")
.replace("VV", "X")
.replace("VIV", "IX")
.replace("XXXXX", "L")
.replace("XXXX", "XL")
.replace("LL", "C")
.replace("LXL", "XC")
.replace("CCCCC", "D")
.replace("CCCC", "CD")
.replace("DD", "M")
.replace("DCD", "CM");
}
Me gusta especialmente este método de resolver este problema en lugar de utilizar muchos ifs y while bucles, o tablas de búsqueda. También es una solución intuitiva al dejar de pensar en el problema, no como un problema numérico.
Esto puede ayudar:
using System;
using System.Text;
public class Test
{
public static string ToRoman(int number)
{
StringBuilder br=new StringBuilder("");
while(number!=0)
{
if(number>=1000)
{
br.Append("M");
number-=1000;
}
if(number>=900)
{
br.Append("CM");
number-=900;
}
if(number>=500)
{
br.Append("D");
number-=500;
}
if(number>=400)
{
br.Append("CD");
number-=400;
}
if(number>=100)
{
br.Append("C");
number-=100;
}
if(number>=90)
{
br.Append("XC");
number-=90;
}
if(number>=50)
{
br.Append("L");
number-=50;
}
if(number>=40)
{
br.Append("XL");
number-=40;
}
if(number>=10)
{
br.Append("X");
number-=10;
}
if(number>=9)
{
br.Append("IX");
number-=9;
}
if(number>=5)
{
br.Append("V");
number-=5;
}
if(number>=4)
{
br.Append("IV");
number-=4;
}
if(number>=1)
{
br.Append("I");
number-=1;
}
}
return br.ToString();
}
public static void Main()
{
Console.WriteLine(ToRoman(int.Parse(Console.ReadLine())));
}
}
He escrito una solución muy simple. Todo lo que tenemos que hacer es dividir y encontrar cuántas veces se produce una combinación particular de letras (o letras) y anexarlas al objeto StringBuilder sb
. También debemos hacer un seguimiento del número restante ( num
).
public static String intToRoman(int num) {
StringBuilder sb = new StringBuilder();
int times = 0;
String[] romans = new String[] { "I", "IV", "V", "IX", "X", "XL", "L",
"XC", "C", "CD", "D", "CM", "M" };
int[] ints = new int[] { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500,
900, 1000 };
for (int i = ints.length - 1; i >= 0; i--) {
times = num / ints[i];
num %= ints[i];
while (times > 0) {
sb.append(romans[i]);
times--;
}
}
return sb.toString();
}
Me gusta la respuesta de André Kramer Orten, muy elegante, me gusta especialmente cómo evita los bucles, pensé en otra forma de manejarlo y también evitar los bucles.
Utiliza la división de enteros y el módulo en la entrada para seleccionar el índice correcto de un conjunto codificado de matrices de cadenas para cada tipo de unidad.
Lo bueno aquí es que puede especificar las conversiones exactas dependiendo de si quiere el número aditivo o substractivo, es decir, IIII vs IV. Aquí utilizo la "forma sustractiva" para todos los números en la forma 5x-1 (4,9,14,19,40,90, etc.)
También sería trivial ampliar esto para permitir números más grandes simplemente ampliando la matriz de miles con otras formas aditivas o sustractivas, es decir, "IV", "V" o "MMMM", "MMMMM".
Para los puntos de bonificación, realmente me aseguro de que el parámetro numérico esté dentro del rango dado para el problema.
public class RomanNumeralGenerator {
static final int MIN_VALUE = 1;
static final int MAX_VALUE = 3999;
static final String[] RN_M = {"", "M", "MM", "MMM"};
static final String[] RN_C = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
static final String[] RN_X = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
static final String[] RN_I = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
public String generate(int number) {
if (number < MIN_VALUE || number > MAX_VALUE) {
throw new IllegalArgumentException(
String.format(
"The number must be in the range [%d, %d]",
MIN_VALUE,
MAX_VALUE
)
);
}
return new StringBuilder()
.append(RN_M[number / 1000])
.append(RN_C[number % 1000 / 100])
.append(RN_X[number % 100 / 10])
.append(RN_I[number % 10])
.toString();
}
}
Mi solución está en la función getRoman:
public String getRoman(int number) {
String riman[] = {"M","XM","CM","D","XD","CD","C","XC","L","XL","X","IX","V","IV","I"};
int arab[] = {1000, 990, 900, 500, 490, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
StringBuilder result = new StringBuilder();
int i = 0;
while (number > 0 || arab.length == (i - 1)) {
while ((number - arab[i]) >= 0) {
number -= arab[i];
result.append(riman[i]);
}
i++;
}
return result.toString();
}
Noté que es bastante fácil de traducir del número entero al número romano, porque siempre hay 1, 5 y 10 para cada dígito (es decir, I , V y X para 1-10, X , L y C para 10-100, etc. ) Es por eso que hice una serie de números romanos para obtener la letra correcta de.
En mi ejemplo, paso por el número entero de un dígito por vez, usando el operador de módulo para obtener el último dígito cada vez. Luego formé el número romano a partir del dígito actual dentro de una declaración de cambio, y lo agregué al comienzo de la cadena asRomanNumerals. Después de que el dígito ha sido traducido, se elimina del número y el índice utilizado para buscar la letra en la matriz se incrementa con dos ( IVX -> XLC ).
public static void main(String[] args) {
// number is the one to be translated into Roman Numerals
int number = 2345;
number = Math.min(3999, Math.max(1, number)); // wraps number between 1-3999
String asRomanNumerals = "";
// Array including numerals in ascending order
String[] RN = {"I", "V", "X", "L", "C", "D", "M" };
int i = 0; // Index used to keep track which digit we are translating
while (number > 0) {
switch(number % 10) {
case 1: asRomanNumerals = RN[i] + asRomanNumerals; break;
case 2: asRomanNumerals = RN[i] + RN[i] + asRomanNumerals; break;
case 3: asRomanNumerals = RN[i] + RN[i] + RN[i] + asRomanNumerals; break;
case 4: asRomanNumerals = RN[i] + RN[i + 1] + asRomanNumerals; break;
case 5: asRomanNumerals = RN[i + 1] + asRomanNumerals; break;
case 6: asRomanNumerals = RN[i + 1] + RN[i] + asRomanNumerals; break;
case 7: asRomanNumerals = RN[i + 1] + RN[i] + RN[i] + asRomanNumerals; break;
case 8: asRomanNumerals = RN[i + 1] + RN[i] + RN[i] + RN[i] +asRomanNumerals; break;
case 9: asRomanNumerals = RN[i] + RN[i + 2] + asRomanNumerals; break;
}
number = (int) number / 10;
i += 2;
}
System.out.println(asRomanNumerals);
}
Solución alternativa basada en la propia solución de OP utilizando una enum
. Además, se incluyen un analizador y pruebas de ida y vuelta.
public class RomanNumber {
public enum Digit {
M(1000, 3),
CM(900, 1),
D(500, 1),
CD(400, 1),
C(100, 3),
XC(90, 1),
L(50, 1),
XL(40, 1),
X(10, 3),
IX(9, 1),
V(5, 1),
IV(4, 1),
I(1, 3);
public final int value;
public final String symbol = name();
public final int maxArity;
private Digit(int value, int maxArity) {
this.value = value;
this.maxArity = maxArity;
}
}
private static final Digit[] DIGITS = Digit.values();
public static String of(int number) {
if (number < 1 || 3999 < number) {
throw new IllegalArgumentException(String.format(
"Roman numbers are only defined for numbers between 1 and 3999 (%d was given)",
number
));
}
StringBuilder sb = new StringBuilder();
for (Digit digit : DIGITS) {
int value = digit.value;
String symbol = digit.symbol;
while (number >= value) {
sb.append(symbol);
number -= value;
}
}
return sb.toString();
}
public static int parse(String roman) {
if (roman.isEmpty()) {
throw new NumberFormatException("The empty string does not comprise a valid Roman number");
}
int number = 0;
int offset = 0;
for (Digit digit : DIGITS) {
int value = digit.value;
int maxArity = digit.maxArity;
String symbol = digit.symbol;
for (int i = 0; i < maxArity && roman.startsWith(symbol, offset); i++) {
number += value;
offset += symbol.length();
}
}
if (offset != roman.length()) {
throw new NumberFormatException(String.format(
"The string ''%s'' does not comprise a valid Roman number",
roman
));
}
return number;
}
/** TESTS */
public static void main(String[] args) {
/* Demonstrating round-trip for all possible inputs. */
for (int number = 1; number <= 3999; number++) {
String roman = of(number);
int parsed = parse(roman);
if (parsed != number) {
System.err.format(
"ERROR: number: %d, roman: %s, parsed: %d/n",
number,
roman,
parsed
);
}
}
/* Some illegal inputs. */
int[] illegalNumbers = { -1, 0, 4000, 4001 };
for (int illegalNumber : illegalNumbers) {
try {
of(illegalNumber);
System.err.format(
"ERROR: Expected failure on number %d/n",
illegalNumber
);
} catch (IllegalArgumentException e) {
// Failed as expected.
}
}
String[] illegalRomans = { "MMMM", "CDCD", "IM", "T", "", "VV", "DM" };
for (String illegalRoman : illegalRomans) {
try {
parse(illegalRoman);
System.err.format(
"ERROR: Expected failure on roman %s/n",
illegalRoman
);
} catch (NumberFormatException e) {
// Failed as expected.
}
}
}
}
Tengo curiosidad de cómo va a terminar esto. Comenzaría a buscar en el mapeo 1,2,3,5,6,7,8,9,10 a I, II, III, IV, V, VI, VII, VII, IX, X ... entonces tú podría buscar en la regla los números romanos: I, II, III se crean por concatenación V, X, L, C, D y M son símbolos para 5, 10, 50, 100, 500 y 1000 Los romanos pensaban que podían guardar espacio para escribir números en lugar de escribir, por ejemplo, IIII para 4 usos IV (es decir, 5 menos 1 ...). Es posible que desee examinar esas reglas, por ejemplo, en http://en.wikipedia.org/wiki/Roman_numerals y capturarlas. en código, por ejemplo, en una clase "RomanNumbers" Si desea hacer trampa, es posible que desee seguir el enlace http://www.moxlotus.alternatifs.eu/programmation-converter.html
Una implementación compacta usando Java TreeMap y recursión:
import java.util.TreeMap;
public class RomanNumber {
private final static TreeMap<Integer, String> map = new TreeMap<Integer, String>();
static {
map.put(1000, "M");
map.put(900, "CM");
map.put(500, "D");
map.put(400, "CD");
map.put(100, "C");
map.put(90, "XC");
map.put(50, "L");
map.put(40, "XL");
map.put(10, "X");
map.put(9, "IX");
map.put(5, "V");
map.put(4, "IV");
map.put(1, "I");
}
public final static String toRoman(int number) {
int l = map.floorKey(number);
if ( number == l ) {
return map.get(number);
}
return map.get(l) + toRoman(number-l);
}
}
Pruebas:
public void testRomanConversion() {
for (int i = 1; i<= 100; i++) {
System.out.println(i+"/t =/t "+RomanNumber.toRoman(i));
}
}
Use estas bibliotecas:
import java.util.LinkedHashMap;
import java.util.Map;
El código:
public static String RomanNumerals(int Int) {
LinkedHashMap<String, Integer> roman_numerals = new LinkedHashMap<String, Integer>();
roman_numerals.put("M", 1000);
roman_numerals.put("CM", 900);
roman_numerals.put("D", 500);
roman_numerals.put("CD", 400);
roman_numerals.put("C", 100);
roman_numerals.put("XC", 90);
roman_numerals.put("L", 50);
roman_numerals.put("XL", 40);
roman_numerals.put("X", 10);
roman_numerals.put("IX", 9);
roman_numerals.put("V", 5);
roman_numerals.put("IV", 4);
roman_numerals.put("I", 1);
String res = "";
for(Map.Entry<String, Integer> entry : roman_numerals.entrySet()){
int matches = Int/entry.getValue();
res += repeat(entry.getKey(), matches);
Int = Int % entry.getValue();
}
return res;
}
public static String repeat(String s, int n) {
if(s == null) {
return null;
}
final StringBuilder sb = new StringBuilder();
for(int i = 0; i < n; i++) {
sb.append(s);
}
return sb.toString();
}
Probando el código:
for (int i = 1;i<256;i++) {
System.out.println("i="+i+" -> "+RomanNumerals(i));
}
La salida:
i=1 -> I
i=2 -> II
i=3 -> III
i=4 -> IV
i=5 -> V
i=6 -> VI
i=7 -> VII
i=8 -> VIII
i=9 -> IX
i=10 -> X
i=11 -> XI
i=12 -> XII
i=13 -> XIII
i=14 -> XIV
i=15 -> XV
i=16 -> XVI
i=17 -> XVII
i=18 -> XVIII
i=19 -> XIX
i=20 -> XX
i=21 -> XXI
i=22 -> XXII
i=23 -> XXIII
i=24 -> XXIV
i=25 -> XXV
i=26 -> XXVI
i=27 -> XXVII
i=28 -> XXVIII
i=29 -> XXIX
i=30 -> XXX
i=31 -> XXXI
i=32 -> XXXII
i=33 -> XXXIII
i=34 -> XXXIV
i=35 -> XXXV
i=36 -> XXXVI
i=37 -> XXXVII
i=38 -> XXXVIII
i=39 -> XXXIX
i=40 -> XL
i=41 -> XLI
i=42 -> XLII
i=43 -> XLIII
i=44 -> XLIV
i=45 -> XLV
i=46 -> XLVI
i=47 -> XLVII
i=48 -> XLVIII
i=49 -> XLIX
i=50 -> L
i=51 -> LI
i=52 -> LII
i=53 -> LIII
i=54 -> LIV
i=55 -> LV
i=56 -> LVI
i=57 -> LVII
i=58 -> LVIII
i=59 -> LIX
i=60 -> LX
i=61 -> LXI
i=62 -> LXII
i=63 -> LXIII
i=64 -> LXIV
i=65 -> LXV
i=66 -> LXVI
i=67 -> LXVII
i=68 -> LXVIII
i=69 -> LXIX
i=70 -> LXX
i=71 -> LXXI
i=72 -> LXXII
i=73 -> LXXIII
i=74 -> LXXIV
i=75 -> LXXV
i=76 -> LXXVI
i=77 -> LXXVII
i=78 -> LXXVIII
i=79 -> LXXIX
i=80 -> LXXX
i=81 -> LXXXI
i=82 -> LXXXII
i=83 -> LXXXIII
i=84 -> LXXXIV
i=85 -> LXXXV
i=86 -> LXXXVI
i=87 -> LXXXVII
i=88 -> LXXXVIII
i=89 -> LXXXIX
i=90 -> XC
i=91 -> XCI
i=92 -> XCII
i=93 -> XCIII
i=94 -> XCIV
i=95 -> XCV
i=96 -> XCVI
i=97 -> XCVII
i=98 -> XCVIII
i=99 -> XCIX
i=100 -> C
i=101 -> CI
i=102 -> CII
i=103 -> CIII
i=104 -> CIV
i=105 -> CV
i=106 -> CVI
i=107 -> CVII
i=108 -> CVIII
i=109 -> CIX
i=110 -> CX
i=111 -> CXI
i=112 -> CXII
i=113 -> CXIII
i=114 -> CXIV
i=115 -> CXV
i=116 -> CXVI
i=117 -> CXVII
i=118 -> CXVIII
i=119 -> CXIX
i=120 -> CXX
i=121 -> CXXI
i=122 -> CXXII
i=123 -> CXXIII
i=124 -> CXXIV
i=125 -> CXXV
i=126 -> CXXVI
i=127 -> CXXVII
i=128 -> CXXVIII
i=129 -> CXXIX
i=130 -> CXXX
i=131 -> CXXXI
i=132 -> CXXXII
i=133 -> CXXXIII
i=134 -> CXXXIV
i=135 -> CXXXV
i=136 -> CXXXVI
i=137 -> CXXXVII
i=138 -> CXXXVIII
i=139 -> CXXXIX
i=140 -> CXL
i=141 -> CXLI
i=142 -> CXLII
i=143 -> CXLIII
i=144 -> CXLIV
i=145 -> CXLV
i=146 -> CXLVI
i=147 -> CXLVII
i=148 -> CXLVIII
i=149 -> CXLIX
i=150 -> CL
i=151 -> CLI
i=152 -> CLII
i=153 -> CLIII
i=154 -> CLIV
i=155 -> CLV
i=156 -> CLVI
i=157 -> CLVII
i=158 -> CLVIII
i=159 -> CLIX
i=160 -> CLX
i=161 -> CLXI
i=162 -> CLXII
i=163 -> CLXIII
i=164 -> CLXIV
i=165 -> CLXV
i=166 -> CLXVI
i=167 -> CLXVII
i=168 -> CLXVIII
i=169 -> CLXIX
i=170 -> CLXX
i=171 -> CLXXI
i=172 -> CLXXII
i=173 -> CLXXIII
i=174 -> CLXXIV
i=175 -> CLXXV
i=176 -> CLXXVI
i=177 -> CLXXVII
i=178 -> CLXXVIII
i=179 -> CLXXIX
i=180 -> CLXXX
i=181 -> CLXXXI
i=182 -> CLXXXII
i=183 -> CLXXXIII
i=184 -> CLXXXIV
i=185 -> CLXXXV
i=186 -> CLXXXVI
i=187 -> CLXXXVII
i=188 -> CLXXXVIII
i=189 -> CLXXXIX
i=190 -> CXC
i=191 -> CXCI
i=192 -> CXCII
i=193 -> CXCIII
i=194 -> CXCIV
i=195 -> CXCV
i=196 -> CXCVI
i=197 -> CXCVII
i=198 -> CXCVIII
i=199 -> CXCIX
i=200 -> CC
i=201 -> CCI
i=202 -> CCII
i=203 -> CCIII
i=204 -> CCIV
i=205 -> CCV
i=206 -> CCVI
i=207 -> CCVII
i=208 -> CCVIII
i=209 -> CCIX
i=210 -> CCX
i=211 -> CCXI
i=212 -> CCXII
i=213 -> CCXIII
i=214 -> CCXIV
i=215 -> CCXV
i=216 -> CCXVI
i=217 -> CCXVII
i=218 -> CCXVIII
i=219 -> CCXIX
i=220 -> CCXX
i=221 -> CCXXI
i=222 -> CCXXII
i=223 -> CCXXIII
i=224 -> CCXXIV
i=225 -> CCXXV
i=226 -> CCXXVI
i=227 -> CCXXVII
i=228 -> CCXXVIII
i=229 -> CCXXIX
i=230 -> CCXXX
i=231 -> CCXXXI
i=232 -> CCXXXII
i=233 -> CCXXXIII
i=234 -> CCXXXIV
i=235 -> CCXXXV
i=236 -> CCXXXVI
i=237 -> CCXXXVII
i=238 -> CCXXXVIII
i=239 -> CCXXXIX
i=240 -> CCXL
i=241 -> CCXLI
i=242 -> CCXLII
i=243 -> CCXLIII
i=244 -> CCXLIV
i=245 -> CCXLV
i=246 -> CCXLVI
i=247 -> CCXLVII
i=248 -> CCXLVIII
i=249 -> CCXLIX
i=250 -> CCL
i=251 -> CCLI
i=252 -> CCLII
i=253 -> CCLIII
i=254 -> CCLIV
i=255 -> CCLV
After doing some research and analysing answers above, I ended up with this:
package roman;
public class RomanNumbers {
public static final int[] decimal = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
public static final String[] letters = {"I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M"};
public static String stringToRoman(int num) {
String roman = "";
if (num < 1 || num > 3999) {
System.out.println("Invalid roman number value!");
}
while (num > 0) {
int maxFound = 0;
for (int i=0; i < decimal.length; i++) {
if (num >= decimal[i]) {
maxFound = i;
}
}
roman += letters[maxFound];
num -= decimal[maxFound];
}
return roman;
}
}
Unit tests also passed:
package roman;
import static org.junit.Assert.*;
import org.junit.Test;
public class RomanNumbersTest {
@Test
public void testReturn1() {
String actual = RomanNumbers.stringToRoman(1);
String expected = "I";
assertEquals(expected, actual);
}
@Test
public void testReturn5() {
String actual = RomanNumbers.stringToRoman(5);
String expected = "V";
assertEquals(expected, actual);
}
@Test
public void testReturn2() {
String actual = RomanNumbers.stringToRoman(2);
String expected = "II";
assertEquals(expected, actual);
}
@Test
public void testReturn4() {
String actual = RomanNumbers.stringToRoman(4);
String expected = "IV";
assertEquals(expected, actual);
}
@Test
public void testReturn399() {
String actual = RomanNumbers.stringToRoman(399);
String expected = "CCCXCIX";
assertEquals(expected, actual);
}
@Test
public void testReturn3992() {
String actual = RomanNumbers.stringToRoman(3992);
String expected = "MMMCMXCII";
assertEquals(expected, actual);
}
}
I did this before three years, may be it helps you:
public class ToRoman
{
public static String toRoman(int number)
{
StringBuilder br = new StringBuilder("");
while(number!=0)
{
while(number>=1000)
{
br.append("M");
number-=1000;
}
while(number>=900)
{
br.append("CM");
number-=900;
}
while(number>=500)
{
br.append("D");
number-=500;
}
while(number>=400)
{
br.append("CD");
number-=400;
}
while(number>=100)
{
br.append("C");
number-=100;
}
while(number>=90)
{
br.append("XC");
number-=90;
}
while(number>=50)
{
br.append("L");
number-=50;
}
while(number>=40)
{
br.append("XL");
number-=40;
}
while(number>=10)
{
br.append("X");
number-=10;
}
while(number>=9)
{
br.append("IX");
number-=9;
}
while(number>=5)
{
br.append("V");
number-=5;
}
while(number>=4)
{
br.append("IV");
number-=4;
}
while(number>=1)
{
br.append("I");
number-=1;
}
}
return br.toString();
}
public static void main(String [] args)
{
System.out.println(toRoman(2000));
}
}
Simplest solution:
public class RomanNumerals {
private static int [] arabic = {50, 40, 10, 9, 5, 4, 1};
private static String [] roman = {"L", "XL", "X", "IX", "V", "IV", "I"};
public static String convert(int arabicNumber) {
StringBuilder romanNumerals = new StringBuilder();
int remainder = arabicNumber;
for (int i=0;i<arabic.length;i++) {
while (remainder >= arabic[i]) {
romanNumerals.append(roman[i]);
remainder -= arabic[i];
}
}
return romanNumerals.toString();
}
}
String convert(int i){
String ones = "";
String tens = "";
String hundreds = "";
String thousands = "";
String result ;
boolean error = false;
Vector v = new Vector();
//assign passed integer to temporary value temp
int temp=i;
//flags an error if number is greater than 3999
if (temp >=4000) {
error = true;
}
/*loops while temp can no more be divided by 10.
Lets say i = 3254, then temp is also 3254 at line 14.
3254
3254/10 = 25 / / 3254%10 = 4
/ /
now temp = 25 325 4 - here 4 is added to the vector v''s 0th index.
/ /
now temp = 32 32 5 - here 5 is added to the vector v''s 1st index.
/ /
now temp = 3 3 2 - here 2 is added to the vector v''s 2nd index, and loop exits
/ / since temp/10 = 0
0 3 - here 3 is not added to the vector v''s 3rd index as loop exits when
temp/10 = 0.
*/
while (temp/10 != 0) {
if (temp / 10 != 0 && temp <4000) {
v.add(temp%10);
temp = temp / 10;
}else {
break;
}
}
//therefore you have to add temp one last time to the vector
v.add(temp);
//as in the example now you have 4,5,2,3 respectively in v''s 0,1,2,3 indices.
for (int j = 0; j < v.size(); j++) {
//you see that v''s 0th index has number of ones. So make them roman ones here.
if (j==0) {
switch (v.get(0).toString()){
case "0" : ones = ""; break;
case "1" : ones = "I"; break;
case "2" : ones = "II"; break;
case "3" : ones = "III"; break;
case "4" : ones = "IV"; break;
case "5" : ones = "V"; break;
case "6" : ones = "VI"; break;
case "7" : ones = "VII"; break;
case "8" : ones = "VIII"; break;
case "9" : ones = "IX"; break;
}
//in the second iteration of the loop (when j==1)
//index 1 of v is checked. Now you understand that v''s 1st index
//has the tens
} else if (j == 1) {
switch (v.get(1).toString()){
case "0" : tens = ""; break;
case "1" : tens = "X"; break;
case "2" : tens = "XX"; break;
case "3" : tens = "XXX"; break;
case "4" : tens = "XL"; break;
case "5" : tens = "L"; break;
case "6" : tens = "LX"; break;
case "7" : tens = "LXX"; break;
case "8" : tens = "LXXX"; break;
case "9" : tens = "XC"; break;
}
} else if(j == 2){ //and hundreds
switch (v.get(2).toString()){
case "0" : hundreds = ""; break;
case "1" : hundreds = "C"; break;
case "2" : hundreds = "CC"; break;
case "3" : hundreds = "CCC"; break;
case "4" : hundreds = "CD"; break;
case "5" : hundreds = "D"; break;
case "6" : hundreds = "DC"; break;
case "7" : hundreds = "DCC"; break;
case "8" : hundreds = "DCCC"; break;
case "9" : hundreds = "CM"; break;
}
} else if(j == 3){ //and finally thousands.
switch (v.get(3).toString()){
case "0" : thousands = ""; break;
case "1" : thousands = "M"; break;
case "2" : thousands = "MM"; break;
case "3" : thousands = "MMM"; break;
}
}
}
if (error) {
result = "Error!";
}else{
result = thousands + hundreds + tens + ones;
}
return result;
}
enum Numeral {
I(1), IV(4), V(5), IX(9), X(10), XL(40), L(50), XC(90), C(100), CD(400), D(500), CM(900), M(1000);
int weight;
Numeral(int weight) {
this.weight = weight;
}
};
public static String roman(long n) {
if( n <= 0) {
throw new IllegalArgumentException();
}
StringBuilder buf = new StringBuilder();
final Numeral[] values = Numeral.values();
for (int i = values.length - 1; i >= 0; i--) {
while (n >= values[i].weight) {
buf.append(values[i]);
n -= values[i].weight;
}
}
return buf.toString();
}
public static void test(long n) {
System.out.println(n + " = " + roman(n));
}
public static void main(String[] args) {
test(1999);
test(25);
test(944);
test(0);
}
import java.util.Scanner;
import java.io.*;
public class LetteredNumerationSystem {
public static void main(String args[]) {
File file = new File("lettered.in");
try {
Scanner input = new Scanner(file);
int dataCollect = input.nextInt();
int sum = 0;
String lineInput = "";
for (int i = 0; i <= dataCollect; i++) {
while (input.hasNext()) {
lineInput = input.next();
char lineArray[] = lineInput.toCharArray();
for (int j = 0; j < lineArray.length; j++) {
if (lineArray[j] == ''A'') {
sum += 1;
} else if (lineArray[j] == ''B'') {
sum += 10;
} else if (lineArray[j] == ''C'') {
sum += 100;
} else if (lineArray[j] == ''D'') {
sum += 1000;
} else if (lineArray[j] == ''E'') {
sum += 10000;
} else if (lineArray[j] == ''F'') {
sum += 100000;
} else if (lineArray[j] == ''G'') {
sum += 1000000;
} else if (lineArray[j] == ''X'') {
System.out.println(sum);
sum = 0;
}
}
}
}
} catch (FileNotFoundException e) {
System.out.println("ERROR");
}
}
}
private String convertToRoman(int num) {
String result = "";
while(num > 0){
if(num >= 1000){
result += "M";
num -= 1000;
}else if(num >= 900){
result += "CM";
num -= 900;
}
else if(num >= 500){
result += "D";
num -= 500;
}else if(num >= 400){
result += "CD";
num -= 400;
}else if(num >= 100){
result += "C";
num -= 100;
}else if(num >= 90){
result += "XC";
num -= 90;
}else if(num >= 50){
result += "L";
num -= 50;
}else if(num >= 40){
result += "XL";
num -= 40;
}
else if(num >= 10){
result += "X";
num -= 10;
}else if(num >= 9){
result += "IX";
num -= 9;
}
else if(num >= 5){
result += "V";
num -= 5;
}else if(num >= 4){
result += "IV";
num -= 4;
}else if(num >= 1){
result += "I";
num -= 1;
}
else{
break;
}
}
return result;
}