Java - Roman Numeral validity - java

I am writing a program to add two roman numerals without converting to any bases. I have everything working except I am not sure how to check if my input String is a valid roman numeral or not.
These are the rules to check validity:
Five in a row of any digit is not allowed
Some digits are allowed in runs of up to 4. They are I,X,C, and M. The others (V,L,D) can only appear singly.
Some lower digits can come before a higher digit, but only if they appear singly. E.g. "IX" is ok but "IIIX" is not.
But this is only for pairs of digits. Three ascending numbers in a row is invalid. E.g. "IX" is ok but "IXC" is not.
A single digit with no runs is always allowed
I have not really been able to make much progress with this step and don't have anything working yet. Any help would be great!

Why not use regular expression:
boolean valid = word.matches("^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$");
Look at the post of paxdiablo:
How do you match only valid roman numerals with a regular expression?

Loop through each character in the string.
Use a if conditions to check which character it is.
Use the if conditions to check for the roman numeral rule violations in the adjacent characters to the selected character.
for(int i = 0; i < s.length(); i++){
if (s[i] == 'V'){
**Check if the character before of after is also 'V'. Then it is a violation
}
else if(s[i] == 'L'){
**Conditions for 'L' etc.
}
}

This is what I have come up with based on my rules. Any thoughts on refactoring this to make it simpler?
public static boolean checkValidity (String s1, HashSet<Character> romanNumerals){
HashSet<Character> alreadyContained = new HashSet<Character>();
if (s1.length() == 1 && romanNumerals.contains(s1.charAt(0))){
return true;
}
int i = 0;
while (i < s1.length()){
if (s1.charAt(i) == 'M'){
if (alreadyContained.contains('M')){
return false;
}
int count = 1;
i++;
while (s1.charAt(i) == 'M'){
i++;
count++;
}
alreadyContained.add('M');
if (count >= 5){
return false;
}
}
else if (s1.charAt(i) == 'D'){
if (alreadyContained.contains('D')){
return false;
}
alreadyContained.add('D');
if (!alreadyContained.contains('M')){
alreadyContained.add('M');
}
i++;
if ((i < s1.length()) && (s1.charAt(i) == 'D')){
return false;
}
}
else if (s1.charAt(i) == 'L'){
if (alreadyContained.contains('L')){
return false;
}
alreadyContained.add('L');
if (!alreadyContained.contains('M')){
alreadyContained.add('M');
}
if (!alreadyContained.contains('D')){
alreadyContained.add('D');
}
if (!alreadyContained.contains('C')){
alreadyContained.add('C');
}
i++;
if ((i < s1.length()) && (s1.charAt(i) == 'L')){
return false;
}
}
else if (s1.charAt(i) == 'V'){
if (alreadyContained.contains('V')){
return false;
}
alreadyContained.add('V');
if (!alreadyContained.contains('M')){
alreadyContained.add('M');
}
if (!alreadyContained.contains('D')){
alreadyContained.add('D');
}
if (!alreadyContained.contains('C')){
alreadyContained.add('C');
}
if (!alreadyContained.contains('L')){
alreadyContained.add('L');
}
if (!alreadyContained.contains('X')){
alreadyContained.add('X');
}
i++;
if ((i < s1.length()) && (s1.charAt(i) == 'V')){
return false;
}
}
else if (s1.charAt(i) == 'C'){
if (alreadyContained.contains('C')){
return false;
}
int count = 1;
i++;
if ((i < s1.length()) &&(s1.charAt(i) == 'M' || s1.charAt(i) == 'D')){
i++;
}
else if (i < s1.length() && s1.charAt(i) == 'C'){
while ((i < s1.length()) && (s1.charAt(i) == 'C')){
i++;
count++;
}
}
alreadyContained.add('C');
if (!alreadyContained.contains('M')){
alreadyContained.add('M');
}
if (!alreadyContained.add('D')){
alreadyContained.add('D');
}
if (count >= 5){
return false;
}
}
else if (s1.charAt(i) == 'X'){
if (alreadyContained.contains('X')){
return false;
}
int count = 1;
i++;
if ((i < s1.length()) && (s1.charAt(i) == 'D' || s1.charAt(i) == 'M')){
return false;
}
while ((i < s1.length()) && s1.charAt(i) == 'X'){
i++;
count++;
}
alreadyContained.add('X');
if (count >= 5){
return false;
}
}
else if (s1.charAt(i) == 'I'){
if (alreadyContained.contains('I')){
return false;
}
alreadyContained.add('I');
i++;
int count = 1;
if ((i < s1.length()) && (s1.charAt(i) != 'I' && s1.charAt(i) != 'X' && s1.charAt(i) != 'V')){
return false;
}
else if (i < s1.length() && s1.charAt(i) == 'I'){
while (i < s1.length() && s1.charAt(i) == 'I'){
i++;
count++;
}
if (count >= 4){
return false;
}
}
}
else if (!romanNumerals.contains(s1.charAt(i))){
return false;
}
}
return true;
}

Related

How to reverse for loop?

I have a method with some logic
first it looked like:
static boolean checkWin(char dot) {
if (map[0][0] == dot && map[0][1] == dot && map[0][2] == dot) {
return true;
}
//more code
if (map[0][2] == dot && map[1][1] == dot && map[2][0] == dot) {
return true;
}
return false;
}
With loops I refactored the method:
static boolean checkWin(char dot) {
for (int i = 0; i <map.length ; i++) {
for (int j = 0; j < map[i].length; j++) {
if (map[0][i] == dot && i == 2) {
return true;
}
if (map[1][i] == dot && i == 2) {
return true;
}
if (map[2][i] == dot && i == 2) {
return true;
}
if (map[i][0] == dot && i == 2) {
return true;
}
if (map[i][1] == dot && i == 2) {
return true;
}
if (map[i][2] == dot && i == 2) {
return true;
}
if (map[i][i] == dot && i == 2) {
return true;
}
if (map[0][2] == dot && map[1][1] == dot && map[2][0] == dot) {
return true;
}
}
}
return false;
}
I have a problem with this line of code:
if (map[0][2] == dot && map[1][1] == dot && map[2][0] == dot)
return true;
}
I need to get map[i][?], ? should assume the value 2, 1 and 0 when i equals to 0, 1 and 2 respectively.
How can I achieve it?
Try to decrease it
for (int i = 2; i > = 0; i--) {
}
i will be 2 1 0
P.S
I think you missed 2 there
P.S
If I understand your question correctly, you need to have 2 1 0 inside loop without modifying for itself? In that case try:
for (int i = 3; i < 3; i++) {
... 2 - i
}

How to check if a coordinate is adjacent to another?

I am writing a snake game. I want to write a method to check if the head (index 0) is next to any other body part. I am not sure what is going wrong, but this method does not do anything. I have it set so that if it returns true the game ends (for testing purposes)
Here is my code:
public boolean headNextToBody()
{
boolean xClose = false;
boolean yClose = false;
for(int i = 0; i < bodyParts; i++)
{
if( x[i] == (x[0] + 1) || x[i] == (x[0] - 1))
{
xClose = true;
}
if(y[i] == y[0] + 1 || y[i] == y[0] - 1)
{
yClose = true;
}
}
return (xClose && yClose);
}
Firstly, no need to include the head (at position 0) in the test, as it will always be false.
for(int i = 1; i < bodyParts; i++)
The conditions for adjacency are
(y[i] == y[0]) && (x[i] == (x[0] + 1) || x[i] == (x[0] - 1))
or
(x[i] == x[0]) && (y[i] == (y[0] + 1) || y[i] == (y[0] - 1))
If either of these are true for any non-head point on the snake you can return true immediately, otherwise return false.
You can combine the separate tests into a single if statement:
public boolean headNextToBody()
{
for(int i = 1; i < bodyParts; i++)
{
if(((y[i] == y[0]) && (x[i] == (x[0] + 1) || x[i] == (x[0] - 1))) ||
((x[i] == x[0]) && (y[i] == (y[0] + 1) || y[i] == (y[0] - 1)))
{
return true;
}
}
return false;
}
Alternatively you could shorten the test a little by using some math:
public boolean headNextToBody()
{
for(int i = 1; i < bodyParts; i++)
{
if(1 == ((x[i]-x[0])*(x[i]-x[0]) + (y[i]-y[0])*(y[i]-y[0]))
{
return true;
}
}
return false;
}

Own String parser java which solves mathematical equations wrote down in a string

I've wrote a method/function in Java which returns the result of a given basic equation. This equation will be given as a String and I think I got this method working but don't know why I need this one line of Code because this should work without it. After trying for more than an hour to solve it I gave up and hope you can give me an aswer.
Here the Code:
public static double format(String s) {
char[] c = s.toCharArray();
if(s.contains("(")) {
int openbrackets = 0;
for (int i = 0; i < s.length() - 2; i++) {
if (c[i] == '(') openbrackets++;
else if (c[i] == ')') {
openbrackets--;
if(openbrackets == 0) {
s = s.replace(s.substring(s.indexOf('('), i+1), ""+(format(s.substring(s.indexOf('(')+1, i))));
break;
}
}
}
}
if (s.contains("(")) { // String can still contains brackets
s = "" + format(s);
}
c = s.toCharArray();
for(int i = c.length-1; i >= 0; i--) {
if(c[i] == '+') {
return format(s.substring(0, i)) + format(s.substring(i+1, s.length()));
} else if(c[i] == '-') {
return format(s.substring(0, i)) - format(s.substring(i+1, s.length()));
}
}
for(int i = s.length()-1; i > 0; i--) {
if(c[i] == '*') {
return format(s.substring(0, i)) * Double.parseDouble(s.substring(i+1, s.length()));
} else if (c[i] == '/') {
return format(s.substring(0, i)) / Double.parseDouble(s.substring(i+1, s.length()));
}
}
return s.equals("") ? 0 : Double.parseDouble(s); // I don't understand why I need to do this line
}
Description:
I don't know why I need this s.equals("") ? : because the String never should be empty however when I run it with this equation ((23)+(23-23-432-35-1-2-4231+2312+12323-(-3))*3/2) for example I get an error without it.
I need the parser to convert config Strings into Numbers for example when it comes to screenresolution. I know I can also use Libraries but I want to try these things by myself.
PS: Dont hate me just because I don't use libraries. I really tried to figure it out and I have fun doing it. I would just like to know why I have to write this little Codeline as I don't figure it out...
Edit: Error was a NumberFormatException as the Parsing got an empty String... Got my error now also the OverflowException which was mentioned in the comments...
EDIT: To everyone who MIGHT use something like this in the future:
Here the Code which actually works:
public static double format(String s) {
s = s.replace(" ", "");
s = s.replace("\t", "");
char[] c = s.toCharArray();
if(s.contains("(")) {
int openbrackets = 0;
for (int i = 0; i < s.length(); i++) {
if (c[i] == '(') openbrackets++;
else if (c[i] == ')') {
openbrackets--;
if(openbrackets == 0) {
s = s.replace(s.substring(s.indexOf('('), i+1), ""+(format(s.substring(s.indexOf('(')+1, i))));
break;
}
}
}
}
if (s.contains("(")) s = "" + format(s);
c = s.toCharArray();
for(int i = c.length-1; i > 0; i--) {
if(c[i] == '+') {
return format(s.substring(0, i)) + format(s.substring(i+1, s.length()));
} else if(c[i] == '-') {
return format(s.substring(0, i)) - format(s.substring(i+1, s.length()));
}
}
for(int i = s.length()-1; i > 0; i--) {
if(c[i] == '*') {
return format(s.substring(0, i)) * Double.parseDouble(s.substring(i+1, s.length()));
} else if (c[i] == '/') {
return format(s.substring(0, i)) / Double.parseDouble(s.substring(i+1, s.length()));
}
}
return s.equals("") ? 0 : Double.parseDouble(s);
}
I'm fairly sure this is at least one location in your code where you pass a 0 length string to your format function:
c = s.toCharArray();
for(int i = c.length-1; i >= 0; i--) {
if(c[i] == '+') {
return format(s.substring(0, i)) + format(s.substring(i+1, s.length()));
} else if(c[i] == '-') {
return format(s.substring(0, i)) - format(s.substring(i+1, s.length()));
}
}
Your loop counter in (int i = c.length-1; i >= 0; i--) will get decremented until it is 0 in value if there are no + or - values in the input string.
Then you call format(s.substring(0, i)) where i = 0 so I think this is one place where you will be passing a zero length/empty string to your function.
Please use a debugger and step through your code - not only would it teach you a valuable skill it would also probably give you the answer you're looking for.

check if array contains certain int BEFORE another int

I need to check if an array contains a 1 and then later in the array contains a 2.
What I have coded only checks if both are in there, not if one is before the other. How could I do this?
if(array[i] == 1)
count++;
else if(array[i] == 2)
count++;
}
if(count > 1)
System.out.print("true");
else
System.out.print("false");
Comparing the index of the values works!
if (nums[i] == 1)
value1 = i;
else if(nums[i] == 2)
value2 = i;
}
if (value2 > value1)
System.out.print("true");
else
System.out.print("false");
This oughta do it!
public void hasOneThenTwo(int[] a) {
bool hasOne = false;
for (int i = 0; i < a.length; ++i) {
if (!hasOne && a[i] == 1) {
hasOne = true;
} else if (hasOne && a[i] == 2) {
return true;
}
}
return false;
}

Java Check Balanced Parentheses

I need to write a program that checks if the parenthesis are balanced, which I understand how to do and have already implemented. But, there is a second part that I'm having trouble with,
"Give an algorithm that returns the position in the string of the first offending parenthesis if the string is not properly nested and balanced That is, if an excess right parenthesis is found, return its position; if there are too many left parentheses, return the position of the first excess left parenthesis."
We haven't learned about stacks or regex so I can't utilize those. Below is my implementation to check if the nested parentheses are balanced.
public static int checkNest(char[] arr) {
int counter = 0,index = 0;
for(int i=0; i<arr.length; i++) {
if(arr[i] == '(')
counter++;
else if(arr[i] == ')')
counter--;
}
if(counter == 0)
index = -1;
return index;
}
Right now the incorrect index will always be 0, I need to manipulate my code to make the index of the incorrect parentheses correctly display.
In general, case when you have multiple parentheses' types, you have to use Stack. You have only one mistake: you should keep counter and increase it when you find an open parenthesis and decrease when finding a close one. When the counter is negative at any step of iteration - then it's not balanced`.
public static boolean isBalanced(String str) {
Deque<Character> stack = new LinkedList<>();
for (int i = 0; i < str.length(); i++) {
char ch = str.charAt(i);
if (ch == '(' || ch == '[' || ch == '{')
stack.push(ch);
else {
if (stack.isEmpty())
return false;
char prv = stack.pop();
if (prv == '(' && ch != ')')
return false;
if (prv == '[' && ch != ']')
return false;
if (prv == '{' && ch != '}')
return false;
}
}
return stack.isEmpty();
}
In case you have only one type of parentheses, then you could have only one counter:
public static boolean isBalanced(String str) {
int count = 0;
for (int i = 0; i < str.length() && count >= 0; i++) {
if (str.charAt(i) == '(')
count++;
else if (str.charAt(i) == ')')
count--;
}
return count == 0;
}
For an extra right parenthesis, you can immediately return the current value of i if the counter is zero, but for an extra left parenthesis, you must continue to parse the string until the end, so you must memorise the position of the last left parenthesis with counter==0:
public static int checkNest(char[] arr) {
int counter = 0,index = -1;
for(int i=0; i<arr.length; i++) {
if(arr[i] == '(') {
if (counter == 0) {
index = i;
}
counter++;
} else if(arr[i] == ')') {
if (counter == 0) {
return i;
}
counter--;
}
}
if (counter == 0) {
return -1;
}
return index;
}
public static int checkNest(char[] arr) {
int counter = 0,index = 0;
for(int i=0; i<arr.length; i++) {
// Only one incorrect parentheses.
index = i;
if(arr[i] == '(')
counter++;
else if(arr[i] == ')')
counter--;
}
if(counter == 0)
index = -1;
return index;
}

Categories