Roman Numeral to Integer: what is wrong with my code - java

So I'm trying to make a converter from roman numerals to integers. What I have so far is this:
public int toNumber(String n){
int number = 0;
int first = 1;
int last = 0;
String substring = n.substring (last, first);
while(substring.equals("I")){
number = number+1;
last = last +1;
first=first +1;
}
while(substring.equals("V")){
number = number+5;
last = last +1;
first=first +1;
}
return number;
}
Obviously I only have I and V in right now, but when I make a tester class to try this out, it returns nothing and keeps letting me put in in a new line.
For the record, here is my tester class
import java.util.Scanner;
public class Tester{
public static void main (String[] args){
RomanNumeralConverter quantity = new RomanNumeralConverter();
Scanner user_input = new Scanner(System.in);
//this is for roman to number
System.out.println("input roman numeral");
String j = user_input.nextLine();
int g = quantity.toNumber(j);
System.out.println(g);
}
}
I'm almost entirely certain that it's a logic problem, but I have no idea what and I feel like I've tried everything I can think of

Your problem is a loop like this:
while(substring.equals("I")) {
number = number+1;
last = last +1;
first=first +1;
}
If the program enters that loop, it will stuck there, because you're not changing the value of substring. Therefore substring.equals("I") will always return true and the only way to stop that loop is terminating the application.
A better way to convert the entered String could be this:
public int toNumber(String n) {
int number = 0;
for (char chr : n.toUpperCase().toCharArray()) {
switch(chr) {
case 'I': number += 1;
break;
case 'V': number += 5;
break;
default: break;
}
}
return number;
}
It converts the provided String to uppercase (viii -> VIII) to avoid checking both cases of every char and converts it into a char array. This array will be used in a foreach loop that takes every single entry of it and tests it in a switch block. Every supported roman numeral has his own case there to increment number accordingly. Currently it supports I and V like in your code. Btw, number += 1 is just a short version of number = number + 1.
After that loop, it returns the converted integer value.

Related

How to use loop for 14 based number system to calculate the sum and product of user input?

I'm in a heap of trouble here, I'm trying to figure out the code for an assignment. What my professor is asking of us is to find the sum and product of two 14 based number 0-9, and A, J, Q, and K by user input.
So far I have code to scan the user input, but I am stuck on the for loop part. I was trying to scan each integer and use the algorithm (value = symbol * 14^(digit-1)) in a for loop, then add all the number. I don't even know where to start with the product of the two.
An alien species uses 14-based numbering system. Their ten digits, 0 >through 9, are the same as our
decimal system. They use A, J, Q and K to represent decimal 10, 11, 12 and 13, respectively. They
hire you to write a Java program to do the summation of their two numbers.
The program should prompt users for two 14-based numbers and then display the summation and the
product of those two entered 14-based numbers. The outputs should also be 14-based. (They are
unwilling to learn our decimal systems!) For example, if inputs are 17 and 96, their sum and product
should be AK and 1020, respectively.
User interface specifications:
Input:
The program prompts users for two 14-based numbers.
▪ A 14-based number is a string that contains a combination of digit characters and
letter characters of A, J, Q and K, case insensitive.
▪ Your program should direct users to input the two numbers, separated by
space(s), on the same line.
▪ The data input line is immediately below the prompt message line. In
other words, after the prompt message is displayed, your program should
force users to enter the two numbers on a new line immediately below
the prompt message.
▪ Your program has to check the validity of input numbers. You can assume input
numbers neither are negative nor contain a decimal point.
o An example of the input session is illustrated as below:
Please enter two 14-based numbers on next line
17 96
Output:
o Two 14-based numbers that are sum and product of the two input 14-based numbers.
Those are the instructions, I hope you can help me out on this loop problem, thank you.
import java.util.Scanner;
public class H6_Ruby{
public static final int A = 10;
public static final int J = 11;
public static final int Q = 12;
public static final int K = 13;
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("Please enter 2 14-based numbers seperated by a space: ");
// for digit 1
String based1 = scan.next();
int basedDig1 = based1.length();
int powerDigit1 = basedDig1 - 1;
for (i = basedDig1[-1]; i
//for digit 2
String based2 = scan.next();
int basedDig2 = based2.length();
int powerDigit2 = basedDig2 -1; //unfinished, stuck
}
}
Firstly, you should convert those alien numbers to decimals. To do so, just google how to convert numbers from one numeric system to other. Then perform arithmetic operations and convert result back. Seems this is a working implementation (try yourself first :) )
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.println("Please enter 2 14-based numbers separated by a space: ");
String inputString = scan.nextLine();
String[] operands = inputString.split(" ");
int humanizedFirst = getHuman(operands[0]);
int humanizedSecond = getHuman(operands[1]);
System.out.println("Sum = " + getAlien(humanizedFirst + humanizedSecond));
System.out.println("Product = " + getAlien(humanizedFirst * humanizedSecond));
}
private static int getHuman(String alienOperand) {
char[] chars = alienOperand.toCharArray();
int result = 0;
int length = chars.length;
for (int i = 0; i < length; i++) {
int part;
switch (chars[i]) {
case 'A':
part = 10;
break;
case 'J':
part = 11;
break;
case 'Q':
part = 12;
break;
case 'K':
part = 13;
break;
default:
part = chars[i] - 48;
}
result += part * Math.pow(14, length - i - 1);
}
return result;
}
private static String getAlien(int humanOperand) {
StringBuilder result = new StringBuilder();
while (humanOperand > 0) {
int digit = humanOperand % 14;
switch (digit) {
case 10:
result.insert(0, 'A');
break;
case 11:
result.insert(0, 'J');
break;
case 12:
result.insert(0, 'Q');
break;
case 13:
result.insert(0, 'K');
break;
default:
result.insert(0, digit);
}
humanOperand -= digit;
humanOperand /= 14;
}
return result.toString();
}
}

How to use boolean to add numbers input by user?

I am writing this program for school work that asks the user to input a sequence of letters and numbers and determine whether it is a digit or not.
My teacher wants me to add up the characters that are digits(numbers) and output it as "Your numbers added up together are: place added number here"
and output the letters are a string saying "These are your letters: *place letters here."
I think I got the code right that determines whether it is a digit or not but how do I end up adding them? I tried using an if statement that checked if Character.isDigit is true but I keep getting errors and I think I'm writing it totally wrong. Any response would be greatly appreciated.
Here is my code:
import java.util.*;
import java.util.Scanner;
public class MyClass
{
public static void main(String args[])
{
int sum1 = 0;
String stringFull = "";
boolean isTrue = Character.isDigit(string1.charAt(i));
Scanner getString = new Scanner(System.in);
System.out.println("Please enter a sequence of letters: ");
String string1 = getString.nextLine();
for(int i = 0; i < 5; i++)
{
if (Character.isDigit(string1.charAt(i)))
{
sum1 += Character.getNumericValue(string1.charAt(i));
} else {
stringFull += string1.charAt(i);
}
if (isTrue)
{
System.out.println(sum1 * sum1);
}
}
}
}
You will get compilation error for below as i wasn't declared before this line
boolean isTrue = Character.isDigit(string1.charAt(i));
instead you should initialize it with false
boolean isTrue = false;
Then, your loop should loop till given string length, but you have hard-coded to 5, which will cause exception at runtime when string length is less than 5.
for(int i = 0; i < 5; i++)
should change to
for(int i = 0; i < string1.length(); i++)
Also, inside you for loop you are have following line of code, but you have never changed isTrue value inside the loop.
if (isTrue)
{
System.out.println(sum1 * sum1);
}
And, I think, right place to change isTrue value, where you are checking for digit.
if (Character.isDigit(string1.charAt(i)))
{
sum1 += Character.getNumericValue(string1.charAt(i));
isTrue = true;
}
You should use
Integer.parseInt(String.valueOf(string1.charAt(i)))
which returns the number, instead of
Character.getNumericValue(string1.charAt(i))
which returns the ascii code for the number

Converting roman numerals to arabic

I'm new to Java and I need to write a program that converts roman numerals to arabic numbers.
I cannot use some functions because I'm not allowed to change the begging neither the end of the given code. I need to do everything inside the the public static void main function.
I started to search on Google and started to code. From now, I can convert only "one-letter" numerals (as X, I, V...) to arabic numbers but I cannot do this to more than elaborated numerals (XI, CCC, IX, IV...).
Can someone help me? I'm really new to Java. It's my first program language and I'm struggling to understand it.
Here is my code:
import java.util.Scanner;
class Roman {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int[] numbers = {1000, 500, 100, 50, 10, 5, 1 };
String symbols = "MDCLXVI";
/*******************************************
* Complete your program
*******************************************/
System.out.print("Enter a roman numeral");
final int MAX = 3999;
Scanner keyb = new Scanner(System.in);
String roman = keyb.next();
roman=roman.toUpperCase();
if(roman.matches(".*[0-9].*") || !roman.matches("[M|D|C|L|X|V|I]*")){
System.out.println("Impossible to convert. Wrong roman numeral");
}
int i = 0; //position in the string romain
int arabic = 0; // Arabic numeral equivalent of the part of the string that
// has been converted so far
int number;
while (i < roman.length()){
char letter = roman.charAt(i); // letter at the current position in the string
if (letter == 'I'){
number = 1;
} else if (letter == 'V'){
number = 5;
} else if (letter == 'X'){
number = 10;
} else if (letter == 'L'){
number = 50;
} else if (letter == 'C'){
number = 100;
} else if (letter == 'D'){
number = 500;
} else if (letter == 'M'){
number = 1000;
} else {
number = -1;
}
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).
number = roman.charAt(i);
int nextNumber = number;
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;
}
}
System.out.println(number);
} // end while
/*******************************************
* Do not change after this line.
*******************************************/
}
}
I would suggest using an enumeration for your individual roman numerals. That makes the code nicely encapsulated.
public enum Roman {
I(1), V(5), X(10), L(50), C(100), D(500), M(1000);
private final int value;
private Roman(int value) {
this.value = value;
}
public int toInt() {
return value;
}
}
Converting a single roman numeral to an integer becomes trivial. For example:
Roman.valueOf("X").toInt();
The only complex bit is coping with "IX" and "XC" type of values. The easy way to identify these is that they are the only time when the numerals are not in descending order of value. Checking for this can be added as methods to the enum itself (to continue encapsulation):
public enum Roman {
public boolean shouldCombine(Roman next) {
return this.value < next.value;
}
public int toInt(Roman next) {
return next.value - this.value;
}
}
Now putting it all together:
List<Roman> romans = new ArrayList<>();
input.chars().mapToObj(Character::valueOf)
.map(Roman::valueOf).forEach(romans::add);
int value = 0;
while (!romans.isEmpty()) {
Roman current = romans.remove(0);
if (!romans.isEmpty() && current.shouldCombine(romans.get(0))
value += current.toInt(romans.remove(0));
else
value += current.ToInt();
}
The first part of this code uses Java 8 features to convert the string to roman numerals. Let me know if you find that confusing and I'll convert it to traditional iteration.
Here is one way to do it:
import java.util.Scanner;
class Roman {
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
int[] numbers = { 1000, 500, 100, 50, 10, 5, 1 };
String symbols = "MDCLXVI";
/*******************************************
* Complete your program
*******************************************/
System.out.print("Enter a roman numeral: ");
final int MAX = 3999;
Scanner keyb = new Scanner(System.in);
String roman = keyb.next();
keyb.close(); // don't want a resource leak
roman = roman.toUpperCase();
if (roman.matches(".*[0-9].*") || !roman.matches("[M|D|C|L|X|V|I]*")) {
System.out.println("Impossible to convert. Wrong roman numeral");
}
int i = 0; // position in the Roman string
int current = 0; // the current Roman numeral character to Arabic
// conversion
int previous = 0; // start previous at zero, that way when
// current is greater than previous in the first
// run, nothing will be subtracted from current
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 the current position in
// the string
// switch statement is easier to read than if - else if - else
switch (letter) {
case ('I'):
current = 1;
break;
case ('V'):
current = 5;
break;
case ('X'):
current = 10;
break;
case ('L'):
current = 50;
break;
case ('C'):
current = 100;
break;
case ('D'):
current = 500;
break;
case ('M'):
current = 1000;
break;
}
if (current > previous) {
// subtract previous * 2 because previous was added to arabic
// once already
arabic += current - (previous * 2);
} else {
// if current is less than or equal to previous then add it to
// arabic
arabic += current;
}
previous = current; // set previous equal to current to check
// for less-than on next iteration
i += 1; // move on to next position in the string
} // end while
// print the Arabic conversion after the loop is done
System.out.println("Arabic: " + arabic);
/*******************************************
* Do not change after this line.
*******************************************/
}
}
In your code, the conditionals after i++ are not necessary since the while(i < roman.length()) conditional stops the loop once i >= roman.length().
Yet another way to do it: switch out the while loop with a for loop and a nested for loop. The outer for loop iterates over each character in the Roman numeral string. The inner for loop iterates over each character in the symbols string. If there is a match between the Roman numeral character and the symbols character, then current is set to the corresponding index in numbers and the inner loop breaks.
for(int i = 0; i < roman.length(); i++) {
for(int s = 0; s < symbols.length(); s++) {
if(roman.charAt(i) == symbols.charAt(s)) {
current = numbers[s];
break;
}
}
if (current > previous) {
// subtract previous * 2 because previous was added to arabic
// once already
arabic += current - (previous * 2);
} else {
// if current is less than or equal to previous then add it to
// arabic
arabic += current;
}
previous = current; // set previous equal to current to check
// for less-than on next iteration
}
This is "one look ahead" in Formal Languages. The only way to solve this problem is to compare position 0 to the next char. If value is less than, value is substracted from the acccumulator, if >=, it is added.

Debugging Object Oriented Programming code output in java

I've been following Tony Gaddis's programming challenges in his book and I've tried doing the "vowels and consonants program". The program will ask the user to input any string, and then it will count the number of vowels or consonants within that string. I was able to code most of it but there has been a problem with the output. Hope you guys can help me with this one.
The problem is like this:
************************|
1 - Count Vowels
2 - Count Consonants
3 - Exit
Enter mode:1
****VOWELS****
Enter words:abracadabra
NUMBER OF VOWELS: 5
Do you want to input again(y/n):n
************************|
1 - Count Vowels
2 - Count Consonants
3 - Exit
Enter mode:1
(and then it'll just end here)
First, I chose mode 1 for counting vowels and then if typed in any string. Then, it did successfully count the number of vowels and it will ask me if i want to input again, I've typed in n for no. The code went back to choosing modes and then, I enter 1 again to count for vowels. This time, it did nothing. It just stopped, where supposedly I should enter a string again and etc. The same thing happens also when I choose 2 for counting consonants.
Here is my code:
PART 1:
package Test;
public class VowelMain {
private String words;
private int vowel = 0;
public VowelMain(String w){
words = w;
setVowel(words);
}
public void setVowel(String words){
char[]chunks = words.toCharArray();
for(int x = 0;x < chunks.length;x++){
if(chunks[x]=='a' || chunks[x]=='e' || chunks[x]=='i' || chunks[x]=='o' || chunks[x]=='u'){
vowel += 1;
}
}
}
public int getVowel(){
return vowel;
}
}
PART II:
package Test;
public class ConsonantMain {
private String words;
private int consonant = 0;
public ConsonantMain(String w){
words = w;
setConsonant(words);
}
public void setConsonant(String words){
char[]chunks = words.toCharArray();
for(int x = 0;x < chunks.length;x++){
if(chunks[x]=='a' || chunks[x]=='e' || chunks[x]=='i' || chunks[x]=='o' || chunks[x]=='u'){
}else{
consonant += 1;
}
}
}
public int getConsonant(){
return consonant;
}
}
PART III:
package Test;
import java.util.Scanner;
public class TestMain {
public static void main(String[]args){
int mode = getMode();
operation(mode);
}
public static void operation(int mode){
Scanner hold = new Scanner(System.in);
String words;
String response;
while(mode == 1 || mode == 2 || mode == 3){
switch(mode){
case 1:
System.out.print("****VOWELS****\n");
do{
System.out.print("Enter words:");
words = hold.nextLine();
VowelMain t = new VowelMain(words);
System.out.println("NUMBER OF VOWELS: " + t.getVowel());
System.out.print("Do you want to input again(y/n):");
response = hold.nextLine();
if(response.equalsIgnoreCase("n")){
mode = -1;
getMode();
}
}while(response.equalsIgnoreCase("y"));
break;
case 2:
System.out.print("****CONSONANTS****\n");
do{
System.out.print("Enter words:");
words = hold.nextLine();
ConsonantMain c = new ConsonantMain(words);
System.out.println("NUMBER OF CONSONANTS: " + c.getConsonant());
System.out.print("Do you want to input again(y/n):");
response = hold.nextLine();
if(response.equalsIgnoreCase("n")){
mode = -1;
getMode();
}
}while(response.equalsIgnoreCase("y"));
break;
case 3:
System.exit(0);
break;
default:
System.out.println("ERROR!");
break;
}
}
}
public static int getMode(){
Scanner hold = new Scanner(System.in);
int mode;
System.out.println("************************");
System.out.println("1 - Count Vowels");
System.out.println("2 - Count Consonants");
System.out.println("3 - Exit");
System.out.print("Enter mode:");
mode = hold.nextInt();
return mode;
}
}
Each time you put
mode = -1;
getMode();
You should replace it with:
mode = getMode();
Here's why. As RealSkeptic said, getMode() is returning a temporary mode value, not the mode value being used in your loop. By assigning the loop mode to the temporary mode (through the return statement) your code will work fine.
Your function is terminating after a loop when we input "n" and invokes the getMode function which is needed here after the user inputs "n".
All you have to do is remove the line getMode() from your if statement in your case 2: and case 3: as shown below:
if(response.equalsIgnoreCase("n")){
mode = -1;
getMode();
}
and change it to,
if(response.equalsIgnoreCase("n")){
mode = getMode();
}

binary to base10 in java with main method and TWO classes/method (boolean and

I am a beginner programmer. This is what I have so far. The directions for the question are kind of difficult. Here is what I am trying to accomplish..
You will write a program that converts binary numbers to base 10 numbers. This program will ask the user to enter a binary number. You will have to verify that what is entered by the user only has 0s and 1s. In the case the user entered letters, you have to keep asking the user for another input. When the input is valid, you will convert the binary number to a base 10 number. Please use the Question1.java file provided in the A2.zip file.
Valid input - In order to check if the input is valid your program should call the CheckInputCorrect method, which takes a String as an input parameter and returns a boolean value. An input string is considered valid if it corresponds to a number in binary representation.
More specifically, in the CheckInputCorrect method, you should scan this string to make sure it only contains ‘0’ or ‘1’ characters. As soon as you find a character that is not ‘0’ or ‘1’, the method should returns false. If the method reaches the end of the input string (i.e. all characters are ‘0’ or ‘1’) the method should return true.
Converter - At this point we assume that the input string is valid (checked with the CheckInputCorrect method). To convert the input from binary to base 10, you must implement the BinaryToNumber method. The BinaryToNumber method should take as parameter a String and return an integer, which corresponds to converted value in base 10.
The binary conversion should work as follows. For each digit in the binary number, if the digit is ‘1’ you should add the corresponding decimal value ( 20 for the rightmost digit, 21 for the next digits to the left, 22 for the next one, and so on) to a variable that will hold the final result to be returned. This can be easily accomplished by using a loop.
1) Am I on the right path?
2) I don't exactly know what I am doing and need you to help me figure that out....
Update1:
When I run this vvvv: It says "Please enter a binary number for me to convert: and then a place for me to type in my answer but whatever i put it just returns another box for me to type in but stops and doesn't evaluated anything.
import java.util.Scanner;
public class Question1
{
public static void main(String[] args)
{
System.out.println("Please enter a binary number for me to convert to decimal: ");
Scanner inputKeyboard = new Scanner(System.in);
String inputUser = inputKeyboard.nextLine();
boolean BinaryNumber = false;
String inputString = "";
while (!BinaryNumber){
inputString = inputKeyboard.next();
BinaryNumber = CheckInputCorrect(inputString);
System.out.println("You have given me a " + BinaryNumber + "string of binary numbers.");
}
int finalNumber = BinaryToNumber(inputString);
System.out.println("Congratulations, your binary number is " + finalNumber + ".");
}
public static boolean CheckInputCorrect(String input)
{
for (int i = 0; i < input.length(); i++)
{
while (i < input.length());
if (input.charAt(i) != '0' && input.charAt(i) != '1')
{return false;}
i++;
}
return true;
}
public static int BinaryToNumber(String numberInput)
{
int total = 0;
for (int i = 0; i < numberInput.length(); i++){
if (numberInput.charAt(i)=='1')
{
total += (int)Math.pow(2,numberInput.length() - 1 - i);
}
}
return total;
}
}
Original:
import java.util.Scanner;
public class Question1
{
public static void main(String[] args)
{
int binarynumber;
int arraySize = {0,1};
int[] binaryinput = new int[arraySize];
Scanner input = new Scanner(System.in);
System.out.println("Please enter a binary number");
binarynumber = in.nextInt();
if (binarynumber <0)
{
System.out.println("Error: Not a positive integer");
}
if (CheckInputCorrect) = true;
{
System.out.print(CheckInputCorrect);
}
public static boolean CheckInputCorrect(String input);
{
boolean b = true;
int x, y;
x = 0
y = 1
b = x || y
while (b >= 0 {
System.out.print("Please enter a binary number")
for (int i = 0; i < binarynumber.length; i++)
{
binaryinput[i] = in.nextInt();
if (binaryinput[i] = b.nextInt();
System.out.printl("Binary number is:" + binaryinput);
break outer;
if (binarynumber != b)
{
System.out.println("Error: Not a binary number")
}
return true;
}
}
public static int BinaryToNumber(String numberInput)
{
int remainder;
if (binarynumber <= 1) {
System.out.print(number);
return; // KICK OUT OF THE RECURSION
}
remainder = number %2;
printBinaryform(number >> 1);
System.out.print(remainder);
return 0;
}
}
}
As mentioned in my comments, your updated code contains two errors
while (i < input.length()); is an infinite loop, because it has no body. Therefore i cannot be increased and will stay lower than input.length().
inputString = inputKeyboard.next(); request another input after the first one and the first input will be ignored.
This is a fixed and commented version of your updated code:
public class Question1 {
public static void main(String[] args) {
System.out.println("Please enter a binary number for me to convert to decimal: ");
Scanner inputKeyboard = new Scanner(System.in);
String inputUser = inputKeyboard.nextLine();
//boolean BinaryNumber = false; // not needed anymore
//String inputString = ""; // not needed too
while (!checkInputCorrect(inputUser)) { // there is no reason for using a boolean var here .. directly use the returned value of this method
System.out.println("You have given me an invalid input. Please enter a binary number: "); // changed this message a little bit
inputUser = inputKeyboard.nextLine(); // re-use the "old" variable inputUser here
}
int finalNumber = binaryToNumber(inputUser);
System.out.println("Congratulations, your decimal number is " + finalNumber + ".");
}
public static boolean checkInputCorrect(String input) { // method names should start with a lower case letter
for (int i = 0; i < input.length(); i++) {
//while (i < input.length()); // this loop is deadly. Please think about why
if (input.charAt(i) != '0' && input.charAt(i) != '1') {
return false;
}
//i++; // what is the purpose of this? The "for" loop will increment "i" for you
}
return true;
}
public static int binaryToNumber(String numberInput) { //method name ... lower case letter ;)
int total = 0;
for (int i = 0; i < numberInput.length(); i++) {
if (numberInput.charAt(i) == '1') {
total += (int) Math.pow(2, numberInput.length() - 1 - i);
}
}
return total;
}
}

Categories

Resources