Roman Numeral to Number Conversion [duplicate] - java

This question already has answers here:
Converting Roman Numerals To Decimal
(30 answers)
Closed 9 years ago.
Trying to write program to read in a string of characters that represent a Roman numeral (from user input) and then convert it to Arabic form (an integer). For instance, I = 1, V = 5, X = 10 etc.
Basically, the constructor that takes a parameter of type String must interpret the string (from user input) as a Roman numeral and convert it to the corresponding int value.
Is there an easier way to solve this besides the below in progress (which isn't compiling as yet):
import java.util.Scanner;
public class RomInt {
String roman;
int val;
void assign(String k)
{
roman=k;
}
private class Literal
{
public char literal;
public int value;
public Literal(char literal, int value)
{
this.literal = literal;
this.value = value;
}
}
private final Literal[] ROMAN_LITERALS = new Literal[]
{
new Literal('I', 1),
new Literal('V', 5),
new Literal('X', 10),
new Literal('L', 50),
new Literal('C', 100),
new Literal('D', 500),
new Literal('M', 1000)
};
public int getVal(String s) {
int holdValue=0;
for (int j = 0; j < ROMAN_LITERALS.length; j++)
{
if (s.charAt(0)==ROMAN_LITERALS[j].literal)
{
holdValue=ROMAN_LITERALS[j].value;
break;
} //if()
}//for()
return holdValue;
} //getVal()
public int count()
{
int count=0;
int countA=0;
int countB=0;
int lastPosition = 0;
for(int i = 0 ; i < roman.length(); i++)
{
String s1 = roman.substring(i,i+1);
int a=getVal(s1);
countA+=a;
}
for(int j=1;j<roman.length();j++)
{
String s2= roman.substring(j,j+1);
String s3= roman.substring(j-1,j);
int b=getVal(s2);
int c=getVal(s3);
if(b>c)
{
countB+=c;
}
}
count=countA-(2*countB);
return count;
}
void disp()
{
int result=count();
System.out.println("Integer equivalent of "+roman+" = " +result);
}
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.print("Please enter Roman Symbol:");
String s = keyboard.nextLine();
RomInt();
}
}

Roman numerals/Decode Example:
class Roman {
private static int decodeSingle(char letter) {
switch (letter) {
case 'M':
return 1000;
case 'D':
return 500;
case 'C':
return 100;
case 'L':
return 50;
case 'X':
return 10;
case 'V':
return 5;
case 'I':
return 1;
default:
return 0;
}
}
public static int decode(String roman) {
int result = 0;
String uRoman = roman.toUpperCase(); //case-insensitive
for (int i = 0; i < uRoman.length() - 1; i++) {//loop over all but the last character
if (decodeSingle(uRoman.charAt(i)) < decodeSingle(uRoman.charAt(i + 1))) {
result -= decodeSingle(uRoman.charAt(i));
} else {
result += decodeSingle(uRoman.charAt(i));
}
}
result += decodeSingle(uRoman.charAt(uRoman.length() - 1));
return result;
}
public static void main(String[] args) {
System.out.println(decode("MCMXC")); //1990
System.out.println(decode("MMVIII")); //2008
System.out.println(decode("MDCLXVI")); //1666
}
}

Use enum, for easy and simple solution. At first define the decimal equivalent weight at roman.
enum Roman{
i(1),iv(4),v(5), ix(9), x(10);
int weight;
private Roman(int weight) {
this.weight = weight;
}
};
This is the method to convert decimal to roman String.
static String decToRoman(int dec){
String roman="";
Roman[] values=Roman.values();
for (int i = values.length-1; i>=0; i--) {
while(dec>=values[i].weight){
roman+=values[i];
dec=dec-values[i].weight;
}
}
return roman;
}

You can try using a Hashmap to store the roman numerals and equivalent arabic numerals.
HashMap test = new HashMap();
test.add("I",1);
test.add("V",5);
test.add("X",10);
test.add("L",50);
test.add("C",100);
test.add("D",500);
test.add("M",1000);
//This would insert all the roman numerals as keys and their respective arabic numbers as
values.
To retrieve respective arabic numeral one the input of the user, you can use following peice of code:
Scanner sc = new Scanner(System.in);
System.out.println(one.get(sc.next().toUpperCase()));
//This would print the respective value of the selected key.This occurs in O(1) time.
Secondly,
If you only have these set of roman numerals, then you can go for simple switch case statement.
switch(sc.next().toUpperCase())
{
case 'I' :
System.out.println("1");
break;
case 'V'
System.out.println("5");
break;
.
.
.
& so on
}
Hope this helps.

How about this:
public static int convertFromRoman(String roman) {
Map<String, Integer> v = new HashMap<String, Integer>();
v.put("IV", 4);
v.put("IX", 9);
v.put("XL", 40);
v.put("CD", 400);
v.put("CM", 900);
v.put("C", 100);
v.put("M", 1000);
v.put("I", 1);
v.put("V", 5);
v.put("X", 10);
v.put("L", 50);
v.put("D", 500);
int result = 0;
for (String s : v.keySet()) {
result += countOccurrences(roman, s) * v.get(s);
roman = roman.replaceAll(s, "");
}
return result;
}
public static int countOccurrences(String main, String sub) {
return (main.length() - main.replace(sub, "").length()) / sub.length();
}
Not sure I've got all possible combinations as I'm not an expert in roman numbers. Just make sure that the once where you substract come first in the map.

Your compilation issue can be resolved with below code. But surely its not optimized one:
public static void main(String[] args)
{
Scanner keyboard = new Scanner(System.in);
System.out.print("Please enter Roman Symbol:");
String s = keyboard.nextLine();
RomInt temp = new RomInt();
temp.getVal(s);
temp.assign(s);
temp.disp();
}

Related

Calculator for metric distance from an expression that contains different scales

public enum Operator {
PLUS("+"),
MINUS("-");
private final String operator;
Operator(String operator) {
this.operator = operator;
}
public String getOperator() {
return operator;
}
public static Operator getByValue(String operator) {
for (Operator operatorEnum : Operator.values()) {
if (operatorEnum.getOperator().equals(operator)) {
return operatorEnum;
}
}
throw new IllegalArgumentException("Invalid value");
}
}
//////////
public enum MetricConvertor {
m(1000),
cm(10),
mm(1),
km(1000000),
dm(100);
private int scale;
MetricConvertor(int scale) {
this.scale = scale;
}
public int getScale() {
return scale;
}
}
/////////
public class Application {
public static void main(String[] args) {
int scale = MetricConvertor.valueOf("m").getScale();
}
I wan to create a calculator that is capable of computing a metric distance value from an expression that contains different scales and systems.
Output should be specified by the user.
Only Addition and subtraction is allowed.
Output is in lowest unit.
Expression: 10 cm + 1 m - 10 mm
Result: 1090 mm
I am stuck at this point, how can I add or substract the values for a list and convert them at the lowest scale sistem( eg above mm, but it can be dm if are added for example dm + m + km)
Here is solution
split each string by add/minus and add it to appropriate list
split number and metric in each list(can use matcher) and sum it
result = sumAdd - sumMinus(mm).
Please optimize it, because i don't have time to optimize this code, I need to go to bed :D
Result is in mm, so you have to get lowest metric and recaculate it(leave it to you).
private static int caculator(String exp) {
List<String> addList = new ArrayList<>();
List<String> minusList = new ArrayList<>();
int checkPoint = 0;
boolean op = true;//default first value is plus
// Split string with add/minus
for (int i = 1; i < exp.length(); i++) {
String s = exp.substring(i, i + 1);
if (Operator.PLUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = true;
continue;
}
if (Operator.MINUS.getOperator().equals(s)) {
checkOperator(addList, minusList, op, exp.substring(checkPoint, i).trim());
checkPoint = i + 1;
op = false;
continue;
}
}
// Add last string
checkOperator(addList, minusList, op, exp.substring(checkPoint).trim());
// Get sum each list
int sumAdd = sumList(addList);
int sumMinus = sumList(minusList);
return sumAdd - sumMinus;
}
//sum a list
private static int sumList(List<String> addList) {
int sum = 0;
for (String s: addList) {
String[] arr = s.split(" ");
int value = Integer.parseInt(arr[0]);
int scale = MetricConvertor.valueOf(arr[1]).getScale();
sum += value * scale;
}
return sum;
}
// check operator to put into approriate list
private static void checkOperator(List<String> addList, List<String> minusList, boolean op, String substring) {
if (op) {
addList.add(substring);
} else {
minusList.add(substring);
}
}

reversing an integer in java without a loop

This is an homework problem
Is there a way tor reverse a number in Java without using any loops? The only solution I can think of is reversing it using String and then casting it back to an integer.
If you want to reverse a number withour using any loop you can use Recursion method call. Following program is doing same
public static void reverseMethod(int number) {
if (number < 10) {
System.out.println(number);
return;
} else {
System.out.print(number % 10);
reverseMethod(number / 10);
}
}
public static void main(String args[]) {
int num = 4567;
reverseMethod(num);
}
Even if you were to reverse the number by casting it into a String, you would still need a loop if you want the program to work when having ints of different sizes. If I were to make a method to reverse a number but could not do it with loops, I would probably do it with recursion (which still uses loops indirectly). The code will look something like this:
class Main {
public static void main(String[] args) {
String input = "1234"; // or scanner to take in input can be implemented
System.out.println(Integer.parseInt(reverseInt(input)));
}
public static String reverseInt(String x) {
if (x.length() == 1) {
return x;
} else {
return x.substring(x.length() - 1) + reverseInt(x.substring(0, x.length() - 1));
}
}
}
Hope this helps!
By using reverse() of StringBuilder:
int number = 1234;
String str = String.valueOf(number);
StringBuilder builder = new StringBuilder(str);
builder.reverse();
number = Integer.parseInt(builder.toString());
System.out.println(number);
will print:
4321
if you want reverse method without loop and recursion then use this code
int a=12345;
int b,c,d,e,f;
b=a%10;
c=a%100/10;
d=a%1000/100;
e=a%10000/1000;
f=a%100000/10000;
System.out.println(b+","+c+","+d+","+e+","+f);
you can go like :
public int reverse(int x) {
String o = "";
if (x < 0) {
x *= -1;
String s = Integer.toString(x);
o += "-";
o += new StringBuilder(s).reverse().toString();
}
else {
String s = Integer.toString(x);
o += new StringBuilder(s).reverse().toString();
}
try {
int out = Integer.parseInt(o);
//System.out.println(s);
return out; }
catch (NumberFormatException e) {
return 0;
}
}
This is a solution using recursive method call
public class Tester{
public static int findReverse(int num, int temp){
if(num==0){
return temp;
}else if(num<10){
return temp*10 + num; //up to this is stopping condition
}else{
temp = temp*10 + num%10;
return findReverse(num/10, temp);
}
}
public static void main(String args[]){
int num = 120021;
int reverseNum = findReverse(num, 0);
System.out.println(reverseNum);
if(num == reverseNum)
System.out.println(num +" is a palindrome!");
else
System.out.println(num +" is not a palindrome!");
}
}
This will be fast.
static int reverseNum(int num) {
StringBuilder sb = new StringBuilder(String.valueOf(num));
sb.reverse();
return Integer.parseInt(sb.toString());
}

How to create dynamic array in java with unclear and diffrent inpu INDEXes?

I am new to Java and I needed dynamic Array ... all of thing I found that's for dynamic Array we should use "Array List' that's ok but when I want the indexes to be the power of X that given from input , I face ERORR ! .. the indexes are unclear and the are not specified what is the first or 2th power ! .... can anyone help me how solve it?
public static void main(String[] args) throws Exception {
Scanner Reader = new Scanner(System.in);
ArrayList<Float> Zarayeb = new ArrayList<Float>();
Float s ;
int m;
System.out.print("Add Count of equation Sentences : ");
int N = Reader.nextInt();
if (N == 0)
return;
for (int i = 0; i < N ; i++) {
s = Reader.nextFloat() ;
System.out.print("x^");
m = Reader.nextInt();
if (Zarayeb.get(m)== null)
Zarayeb.add(0 , s);
else{
Float l ;
l = Zarayeb.get(m);
Zarayeb.add (m , l+s);
}
if (i < N-1)
System.out.print("\r+");
}
System.out.print("Add Count of equation Sentences : ");
N = Reader.nextInt();
if (N == 0)
return;
for (int i = 0; i < N ; i++) {
s = Reader.nextFloat() ;
System.out.print("x^");
m = Reader.nextInt();
if (Zarayeb.get(m)== null)
Zarayeb.add(m , s);
else{
Float l ;
l = Zarayeb.get(m);
Zarayeb.add (m , l+s);
}
if (i < N-1)
System.out.print("\r+");
}
System.out.print("Enter X: ");
float X = Reader.nextFloat();
float Sum = 0;
for (int i = 0; i < Zarayeb.size();i++) {
Sum += (Zarayeb.get(i) * Math.pow(X,i));
}
System.out.println("\nThe final answer is : " + Sum);
First I refactored your code a bit to make sense of it:
Main class with the top level logic:
import java.util.Scanner;
public class Main {
private Scanner scanner;
private final Totals totals = new Totals();
public static void main(final String[] args) {
final Main app = new Main();
app.run();
}
private void run() {
scanner = new Scanner(System.in);
try {
readAndProcessEquationSentences();
} finally {
scanner.close();
}
}
private void readAndProcessEquationSentences() {
readSentences(true);
readSentences(false);
System.out.println("The final answer is : " + totals.calculateSum(readBaseInput()));
}
private void readSentences(final boolean useInitialLogic) {
System.out.print("Enter number of equation sentences:");
final int numberOfSentences = scanner.nextInt();
if (numberOfSentences == 0) {
throw new RuntimeException("No sentences");
}
for (int i = 0; i < numberOfSentences; i++) {
Sentence sentence = Sentence.read(scanner);
if (useInitialLogic) {
totals.addInitialSentence(sentence);
} else {
totals.addNextSentence(sentence);
}
if (i < numberOfSentences - 1) {
System.out.print("\r+");
}
}
}
private float readBaseInput() {
System.out.print("Enter base: ");
return scanner.nextFloat();
}
}
Sentence class which represents one equation sentence entered by the user:
import java.util.Scanner;
public class Sentence {
private Float x;
private int y;
public static Sentence read(final Scanner scanner) {
final Sentence sentence = new Sentence();
System.out.println("Enter x^y");
System.out.print("x=");
sentence.x = scanner.nextFloat();
System.out.println();
System.out.print("y=");
sentence.y = scanner.nextInt();
System.out.println();
return sentence;
}
public Float getX() {
return x;
}
public int getY() {
return y;
}
}
Totals class which keeps track of the totals:
import java.util.ArrayList;
import java.util.List;
public class Totals {
private final List<Float> values = new ArrayList<Float>();
public void addInitialSentence(final Sentence sentence) {
if (values.size() <= sentence.getY()) {
addToStart(sentence);
} else {
addToValue(sentence);
}
}
private void addToStart(final Sentence sentence) {
values.add(0, sentence.getX());
}
public void addNextSentence(final Sentence sentence) {
if (values.size() <= sentence.getY()) {
values.add(sentence.getY(), sentence.getX());
} else {
addToValue(sentence);
}
}
private void addToValue(final Sentence sentence) {
Float total = values.get(sentence.getY());
total = total + sentence.getX();
values.add(sentence.getY(), total);
}
public float calculateSum(final float base) {
float sum = 0;
for (int i = 0; i < values.size(); i++) {
sum += (values.get(i) * Math.pow(base, i));
}
return sum;
}
}
I don't have the foggiest idea what this is supposed to do. I named the variables according to this foggy idea.
You are letting the user input values in two separate loops, with a slightly different logic I called 'initial' and 'next'.
In the initial loop you were doing this:
if (Zarayeb.get(m) == null)
Zarayeb.add(0 , s);
In the next loop this:
if (Zarayeb.get(m) == null)
Zarayeb.add(m , s);
There are problems with this because the ArrayList.get(m) will throw an IndexOutOfBoundException if m is out or range. So I changed that to the equivalent of:
if (Zarayeb.size() <= m) {
....
}
However, in the 'next' case this still does not solve it. What should happen in the second loop when an 'm' value is entered for which no element yet exists in the ArrayList?
Why do you need to enter sentences in two loops?
What is the logic supposed to achieve exactly?

How can I scan a string for only four specific characters?

I want the user to input a DNA sequence, if it doesn't have the letters A, C, T, or G then it should print out an error. But how can I scan the string entered for those specific characters in the constructot method DNASequence?
heres what I have so far.
import java.util.*;
public class DNASequence {
private String DNASequence;//create a private static variable that can be accessed
public static void main(String[] args){
Scanner input = new Scanner(System.in);
System.out.println("Please input a sequence of DNA: ");
String DNAInput = input.nextLine();
}
public DNASequence(String DNAStrand){//Constructor Method that takes parameter a string and checks to see if its only A, T, C, G.
DNASequence = DNAStrand;
// Invoke the countLetters method to count each letter
int[] counts = countLetters(DNAStrand.toUpperCase());
// Display results
for (int i = 0; i < counts.length; i++) {
if (counts[i] != 0)
System.out.println((char)('a' + i) + " appears " +
counts[i] + ((counts[i] == 1) ? " time" : " times"));
}
}
/** Count each letter in the string */
public static int[] countLetters(String s) {
int[] counts = new int[26];
for (int i = 0; i < s.length(); i++) {
if (Character.isLetter(s.charAt(i)))
counts[s.charAt(i) - 'a']++;
}
return counts;
}
public String toString(){//Method that just returns the stored sequence
return DNASequence;
}
private static char NucleotideBaseCount(char BaseCount){//Method to count bases
}
private static boolean isSubsequenceOf(String DNAStrand){
}
}
You could use the following regular expression for this: ^[ACTG]+$.
To match the input string against the regex, use String.matches().
Here in a sample implementation based on #NPE 's comment:
import java.util.*;
public class DNASequence
{
private String DNASequence = null; //create a private static variable that can be accessed
public static void main(String[] args)
{
System.out.println("Please input a sequence of DNA: ");
DNASequence dnaS = new DNASequence((new Scanner(System.in)).nextLine().toUpperCase());
}
//Constructor Method that takes parameter a string and checks to see if its only A, T, C, G.
public DNASequence(String DNAStrand) throws IllegalArgumentException
{
if (DNAStrand.matches("^[ATCG]+$"))
{
DNASequence = DNAStrand;
}
else
{
throw new IllegalArgumentException("DNA Sequences should only contain A, T, C, G charaters");
}
}
/** Count each letter in the string */
public int[] countLetters() throws IllegalArgumentException
{
int[] counts = new int[4];
if (DNASequence != null)
{
for (int i = 0; i < DNASequence.length(); i++)
{
switch (DNASequence.charAt(i))
{
case 'A':
counts[0]++;
break;
case 'T':
counts[1]++;
break;
case 'C':
counts[2]++;
break;
case 'G':
counts[3]++;
break;
default:
throw new IllegalArgumentException("DNA Sequences should only contain A, T, C, G charaters, found: " + DNASequence.charAt(i));
}
}
}
return counts;
}
//Method that just returns the stored sequence
public String toString()
{
return DNASequence;
}
private char NucleotideBaseCount(char BaseCount){//Method to count bases
return 'a'; // replace with real implementation
}
private boolean isSubsequenceOf(String DNAStrand)
{
return false; // repalce with real implementation
}
}

Postfix evaluation in java with stack

I made this program that evaluates a postfix expression.
It works fine if only single digit numbers are used.
My problem is how do I push multiple-digit numbers if input has spaces?
ex. input: 23+34*- output is -7
but if I input: 23 5 + output is only 3(which is the digit before the space)
it should have an output of 28
my codes:
public class Node2
{
public long num;
Node2 next;
Node2(long el, Node2 nx){
num = el;
next = nx;
}
}
class stackOps2
{
Node2 top;
stackOps2(){
top = null;
}
public void push(double el){
top = new Node2(el,top);
}
public double pop(){
double temp = top.num;
top = top.next;
return temp;
}
public boolean isEmpty(){
return top == null;
}
}
public class ITP {
static stackOps2 so = new stackOps2();
public static final String operator = "+-*/^";
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("Enter the infix:");
String s = input.next();
String output;
InToPost theTrans = new InToPost(s);
output = theTrans.doTrans();
System.out.println("Postfix is " + output + '\n');
System.out.println(output+" is evaluated as: "+evaluate(output));
}
public static double evaluate(String value)throws NumberFormatException{
for(int i=0;i<value.length();i++){
char val = value.charAt(i);
if(Character.isDigit(value.charAt(i))){
String v = ""+val;
so.push(Integer.parseInt(v));
}
else if(isOperator(val)){
double rand1=so.pop();
double rand2=so.pop();
double answer ;
switch(val){
case '+': answer = rand2 + rand1;break;
case '-': answer = rand2 - rand1;break;
case '*': answer = rand2 * rand1;break;
case '^': answer = Math.pow(rand2, rand1);break;
default : answer = rand2 / rand1;break;
}
so.push(answer);
}
else if(so.isEmpty()){
throw new NumberFormatException("Stack is empty");
}
}
return so.pop();
}
public static boolean isOperator(char ch){
String s = ""+ch;
return operator.contains(s);
}
}
This is a small, self-contained example that does all the string parsing and evaluation. The only difference from your example is that it accepts the whole string at once instead of using a Scanner. Note the use of Integer.parseInt -- that's missing in your example. I think you can easily extend this for your needs.
#SuppressWarnings({"rawtypes", "unchecked"})
public static void main(String[] args) {
final String in = "5 9 + 2 * 6 5 * +";
final Deque<Object> s = new LinkedList();
for (String t : in.split(" ")) {
if (t.equals("+")) s.push((Integer)s.pop() + (Integer)s.pop());
else if (t.equals("*")) s.push((Integer)s.pop() * (Integer)s.pop());
else s.push(Integer.parseInt(t));
}
System.out.println(s.pop());
}

Categories

Resources