public static int calcScore(char[] inputChars) {
int gameScore = 0;
for(int i = 0; i < inputChars.length; i++) {
System.out.println(inputChars[i]);
if(inputChars[i] == 'X') {
gameScore += 10;
gameScore += getPointsStrikeSpare(i, inputChars);
} else if (inputChars[i] == '-') {
gameScore += 0;
} else if (inputChars[i] == '/') {
gameScore += 10;
gameScore += getPointsStrikeSpare(i, inputChars);
} else {
gameScore += Character.getNumericValue(inputChars[i]);
}
}
return gameScore;
}
So my problem is that I want to itterate through the inputChars array (created using .toCharArray()) and it works fine but it cannot process the last character.
Here is the content of the input variable: "X-/X5-8/9-X811-4/X".
inputChars is input.toCharArray().
Here is the output when I run the code :
X
-
/
X
5
-
8
/
9
-
X
8
1
1
-
4
/
X
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 18
at betterCalculateScore.getPointsStrikeSpare(betterCalculateScore.java:37)
at betterCalculateScore.calcScore(betterCalculateScore.java:20)
at betterCalculateScore.main(betterCalculateScore.java:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
I have tried using i < inputChars.length - 1 but then it just doesn't count the last character.
Here is the content of getPointsStrikeSpare :
public static int getPointsStrikeSpare(int i, char[] inputChars) {
int points = 0;
if(inputChars[i] == 'X') {
if(inputChars[i+1] == '-') {
points += 0;
} else if (inputChars[i+1]== '/') {
points += 10;
} else {
points += Character.getNumericValue(inputChars[i+1]);
}
if(inputChars[i+2] == '-') {
points += 0;
} else if (inputChars[i+2]== '/') {
points += 10;
} else {
points += Character.getNumericValue(inputChars[i+2]);
}
} else {
if(inputChars[i+1] == '-') {
points += 0;
} else if (inputChars[i+1]== '/') {
points += 10;
} else {
points += Character.getNumericValue(inputChars[i+1]);
}
}
return points;
}
In general, if the value of 'i' is equal to or less than the length of (array_size - 1), a[i] would be valid.
However, in this method, public static int getPointsStrikeSpare(int i, char[] inputChars) one can see that a[i+1] and a[i+2] end up getting queried in different code paths in the if-else structure. So, if your 'i' index already reached the end of the array, this is going to be Out of Bounds.
Ex: X-/X5-8/9-X811-4/X
The size of this is 18. So, the legal values to refer are from 0-17 i.e., a[0] to a[17], since indexing in array starts from 0. Towards the end of the program, index counter 'i' becomes 17.
if(inputChars[i] == 'X') { // VALID
if(inputChars[i+1] == '-') { // INVALID
points += 0;
} else if (inputChars[i+1]== '/') { // INVALID
points += 10;
} else {
points += Character.getNumericValue(inputChars[i+1]); // INVALID
}
if(inputChars[i+2] == '-') { // INVALID
You get the general idea here.
At various places in the public static int getPointsStrikeSpare(int i, char[] inputChars) method, elements are being accessed which do not belong to the array length boundary. Consider the code blocks:
if(inputChars[i+1] == '-')
as well as
if(inputChars[i+2] == '-') {
In the case of i == inputChars.length - 1, both i+1 as well as i+2 exceed the array length, hence the java.lang.ArrayIndexOutOfBoundsException exception.
Related
I have the following method and I wanted to change the for each loops to normal for loops. So I tried something like this
for (int i = 0; i < above.length(); i++) {
char x = above.toCharArray();
if (x == 'x') {
counter++;
}
}
But I know that's wrong. So, what's the right way to change these for each loops to normal for loops?
public static int neighbourconditions(String above, String same, String below){
int counter = 0;
if(above != null){
for(char x : above.toCharArray()){
if(x == 'x'){
counter++;
}
}
}
for (char x : same.toCharArray()){
if (x == 'x'){
counter++;
}
}
if (below != null){
for(char x : below.toCharArray()){
if (x == 'x'){
counter++;
}
}
}
return counter;
}
Just use a basic for loop whose bounds are governed by the length of the string, which is the same as the size of the corresponding character array, e.g. the first loop:
for (char x : above.toCharArray()) {
if (x == 'x') {
counter++;
}
}
would become this:
for (int x=0; x < above.length(); ++x) {
if (above.charAt(x) == 'x') {
counter++;
}
}
You can use above.toCharArray().length and to get the value above.toCharArray()[i] and with collaboration with #chillworld:
You can create an array of char[] array = above.toCharArray(); outside the loop like this :
char[] array = above.toCharArray();
for (int i = 0; i < array.length; i++) {
if (array[i] == 'x') {
counter++;
}
}
I would imagine that you would have to find the length of each string being passed to the method. Example if the content of above is equal to "some_randome_string" you would have to find the length of the string or how many characters are in the string. in this case that would be 19. then you would do;
if <variable != null > {
for (x = 0; x < 18 ; x++) {
code block to be executed
}
}
If you need to count occurances of character x then you may try below or a regex:
String upAbove = above.replaceAll("x","");
int count = above.length() - upAbove.length();
I am currently working on a simple code that will check if an user inputted String contains character(s) that are specified in the for loop.
My current code
import java.util.Scanner;
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.contains("G")) {
G++;
} else {
if (S.contains("R")) {
R++;
} else {
if (S.contains("Y")) {
Y++;
} else {
if (S.contains("B")) {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G/total);
System.out.println(R/total);
System.out.println(Y/total);
System.out.println(B/total);
}
}
As you can see, it checks if the string contains such characters and it will increase the counter of the character by one. However when I run it, I don't receive the results I predicted.
If I input GGRY, it outputs 1 0 0 0. When the desired out put is
0.5
0.25
0.25
0.0
Any help would be appreciated!
The problem is that S.contains returns true if the whole string contains the given character. S.charAt should solve your problem:
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') G++;
else if (S.charAt(i) == 'R') R++;
else if (S.charAt(i) == 'Y') Y++;
else if (S.charAt(i) == 'B') B++;
}
Also, dividing integers will return an integer (rounded down). As such your output would always be 0 unless all the characters are the same. Just cast them to double before printing:
System.out.println((double) G/total);
System.out.println((double) R/total);
System.out.println((double) Y/total);
System.out.println((double) B/total);
Edit: As pointed out by Sumit Gulati in a comment, a switch statement will have better performance in Java 7. Also, as David Conrad pointed out using only ifs in the for loop would work too as the conditions are mutually exclusive.
Your earlier code S.contains("some character") was finding the index of the character in the entire string. Use S.charAt(i) to specifically find the index at ith location in the string.
Finally, you need to convert the integer to floating point in order to print output as floating values.
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') {
G++;
} else {
if (S.charAt(i) == 'R') {
R++;
} else {
if (S.charAt(i) == 'Y') {
Y++;
} else {
if (S.charAt(i) == 'B') {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G * 1.0 / total);
System.out.println(R * 1.0 / total);
System.out.println(Y * 1.0 / total);
System.out.println(B * 1.0 / total);
}
}
I'm working on a program which contains a 2-dimensional 16x32 char array. What I want to do is, starting from a given element in this array, find all the elements that share the same value (in my case a blank space ' ') and that are horizontally and/or vertically linked to each other.
The method I'm using stores the indexes that it finds inside another array, called toShow (public static int toShow[][] = new int[30][30];). The problem is that this method does not seem to process towards the right side. Strangely enough, it seems to work on the other sides... Here's an example:
X1 123
31 1X
211 24
1X1 112X
111 12X34
111•2X32X
1X113X211
In this case, starting from the element marked as •, the method should store every ' ' character and all the neighbor numbers... but this is the result:
1••
1••
1•
1•
1•
1•
It does however usually work if it starts in the lower left corner, even though it does have to turn right!
I don't understand what's wrong with my code... Anyways here is the odd method:
public static void getEmptySurrounding(int xcoord, int ycoord) {
if (toShow[xcoord][ycoord] == 1) {
return;
}
else {
toShow[xcoord][ycoord] = 1;
}
//DOWN
if((ycoord!=29) && ycoord + 1 < 16) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord, ycoord + 1);
}
}
//RIGHT
if((xcoord!=15) && xcoord + 1 < 30) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord + 1, ycoord);
}
}
//UP
if((ycoord!=0) && ycoord - 1 >= 0) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord, ycoord - 1);
}
}
//LEFT
if((xcoord!=0) && xcoord - 1 >= 0) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord - 1, ycoord);
}
}
}
Thank you!
Based on the information you provided I made an application to test your method:
public class Mine {
private static char board[][] = new char[16][32];
private static int toShow[][] = new int[30][30];
public static void main(String[] args) {
int n = 0;
insert(n++, "X1 123");
insert(n++, "31 1X");
insert(n++, "211 24");
insert(n++, "1X1 112X");
insert(n++, "111 12X34");
insert(n++, "111 2X32X");
insert(n++, "1X113X211");
getEmptySurrounding(3, 5);
for (int i = 0; i < 30; i++) {
for (int j = 0; j < 30; j++) {
System.out.print(toShow[j][i]);
}
System.out.println();
}
}
public static void getEmptySurrounding(int xcoord, int ycoord) {
if (toShow[xcoord][ycoord] == 1) {
return;
}
else {
toShow[xcoord][ycoord] = 1;
}
// DOWN
if ((ycoord != 29) && ((ycoord + 1) < 16)) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord, ycoord + 1);
}
}
// RIGHT
if ((xcoord != 15) && ((xcoord + 1) < 30)) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord + 1, ycoord);
}
}
// UP
if ((ycoord != 0) && ((ycoord - 1) >= 0)) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord, ycoord - 1);
}
}
// LEFT
if ((xcoord != 0) && ((xcoord - 1) >= 0)) {
if (board[xcoord][ycoord] == ' ') {
getEmptySurrounding(xcoord - 1, ycoord);
}
}
}
public static void insert(int n, String a) {
for (int i = 0; i < 16; i++) {
board[i][n] = a.length() <= i ? ' ' : a.charAt(i);
}
}
}
At the end it prints out the content of toShow, the relevant part is:
011111100000000000000000000000
011111110000000000000000000000
001111110000000000000000000000
001111100000000000000000000000
001110000000000000000000000000
001110000000000000000000000000
000100000000000000000000000000
000000000000000000000000000000
000000000000000000000000000000
000000000000000000000000000000
which suggest that the method works correctly.
So probably the problem lies elsewhere in your program.
I had an interview in which I did terribly. So, now I'm trying to find the solution to the question. Here is the interview question:
"We have the following mapping:
M: 1000, D: 500, C: 100, L: 50, X: 10, V: 5, I: 1.
And we have the following rules:
Each letter maps to a positive integer value
You add the values together, except...
...when a value (or runs of the same values) is followed by a greater value, you subtract the total of that run of values.
Examples:
IIX -> 8
MCCMIIX -> 1808
We are given this Java method: int valueOfRoman(char roman).
We have implement the Java method: int romanToInt(String s)"
I know it is not a proper roman number system, but that is the actual question.
I was able to code a working solution to a proper Roman system. But I'm unable to change it so that it adapts to these new rules, particularly Rule 3. I have tried, but with no success. The way my solution is right now, for IIX, it prints 10, instead of the correct answer of 8. Here is my code (I also implemented valueOf for my testing):
static int romanToInt(String s) {
char curr;
int currVal;
char prev;
int prevVal;
int total = valueOfRoman(s.charAt(0));
for (int i = 1; i < s.length(); i++) {
curr = s.charAt(i);
currVal = valueOfRoman(curr);
prev = s.charAt(i-1);
prevVal = valueOfRoman(prev);
total += currVal;
if(currVal > prevVal) {
total = total - (2*prevVal);
}
}
return total;
}
static int valueOfRoman(char c) {
if (c == 'M') {
return 1000;
} else if (c == 'D') {
return 500;
} else if (c == 'C') {
return 100;
} else if (c == 'L') {
return 50;
} else if (c == 'X') {
return 10;
} else if (c == 'V') {
return 5;
} else if (c == 'I') {
return 1;
}
return -1;
}
Any help is really appreciated. Specially useful would be if you can tell me how to modify my code. Thanks!
EDIT: I edited the names of the methods so they are clearer.
My take - works with the admittedly small tests you supplied.
static int rom2int(String s) {
if (s == null || s.length() == 0) {
return 0;
}
// Total value.
int total = 0;
// The most recent.
char current = s.charAt(0);
// Total for the current run.
int run = valueOf(current);
for (int i = 1; i < s.length(); i++) {
char next = s.charAt(i);
int value = valueOf(next);
if (next == current) {
// We're in a run - just keep track of its value.
run += value;
} else {
// Up or down?
if (value < valueOf(current)) {
// Gone down! Add.
total += run;
} else {
// Gone UP! Subtract.
total -= run;
}
// Run ended.
run = valueOf(next);
}
// Kee track of most recent.
current = next;
}
return total + run;
}
private void test(String s) {
System.out.println("Value of " + s + " = " + rom2int(s));
}
public void test() {
test("IVX");
test("IIVVL");
test("IIX");
test("MCCMIIX");
test("MVVV");
}
prints
Value of IVX = 4 - Odd!!!
Value of IIVVL = 38
Value of IIX = 8
Value of MCCMIIX = 1808
Value of MVVV = 1015
Here's how I'd approach the problem:
Read the string character by character and during every step note the current character and the previous character.
If the current character is the same as the previous, increase the run length by 1.
If the current character has a smaller value than the previous, add run length * value of previous character to the total, and reset run length to 1.
If the current character has a greater value than the previous, subtract run length * value of previous character from the total, and reset run length to 1.
So, nobody caught my hint. Then I'll give it a try, too. I won't go into the "IVX"- thing because I consider that a syntax error.
int romanToInt( String s ){
int total = 0;
int pivot = 0;
for( int i = s.length()-1; i >= 0; i--){ // We start at the **end**
int current = valueOfRoman((s.charAt(i));
if( current >= pivot ){ // We will have at least "I", so it **will** be > pivot for 1st char.
pivot = current;
total += pivot;
}else{
total -= current;
}
}
return total;
}
Let's see: IIX
i char value total pivot -> total pivot
2 X 10 0 0 > 10 10
1 I 1 10 10 < 9 10
0 I 1 9 10 < 8 10
MCCMIIX
i char value total pivot -> total pivot
6 X 10 0 0 > 10 10
5 I 1 10 10 < 9 10
4 I 1 9 10 < 8 10
3 M 1000 8 10 > 1008 1000
2 C 100 1008 1000 < 908 1000
1 C 100 908 1000 < 808 1000
0 M 1000 808 1000 = 1808 1000
The method leaves out input validation for brevity. I am assuming all input has been checked and consists only of allowed characters according to "the rules".
My take on it.
EDIT CHANGE #2
public class Romans {
private int valueOf(char c) {
if (c == 'M') {
return 1000;
} else if (c == 'D') {
return 500;
} else if (c == 'C') {
return 100;
} else if (c == 'L') {
return 50;
} else if (c == 'X') {
return 10;
} else if (c == 'V') {
return 5;
} else if (c == 'I') {
return 1;
}
return 0;
}
public int rom2int(String s) {
int currVal;
int runValue = 0;
int repetition = 0;
int total = 0;
boolean alreadyAdded = false;
for (int i = 0; i < s.length(); i++) {
currVal = valueOf(s.charAt(i));
if (runValue == 0) {
runValue = currVal;
repetition = 1;
alreadyAdded = false;
} else if (currVal > runValue) {
total = total + (currVal - (runValue * repetition));
repetition = 1;
runValue = currVal;
alreadyAdded = true;
} else if (currVal < runValue) {
if(!alreadyAdded) {
total += (runValue * repetition);
}
repetition = 1;
runValue = currVal;
alreadyAdded = false;
} else {
repetition++;
alreadyAdded = false;
}
}
if (!alreadyAdded) {
total += (runValue * repetition);
}
return total;
}
}
And the main I'm running:
public static void main(String[] args) {
Romans r = new Romans();
String[] inputs = {"MVVV", "IIX","MCCMIIX", "IVX"};
for(String input : inputs) {
System.out.println("Value of " + input + " is: " + r.rom2int(input));
}
}
Outputs:
Value of MVVV is: 1015
Value of IIX is: 8
Value of MCCMIIX is: 1808
Value of IVX is: 9
That's how I did.
It works for those 2 values you mentioned (IIX = 8 and MCCMIIX = 1808):
public static int rom2int(String s)
{
int currVal = 0, prevVal = 0, subTotal = 0, total = 0;
for (int i = 0; i < s.length(); i++) {
currVal = valueOf(s.charAt(i));
if (currVal > 0) {
if (prevVal == 0) {
subTotal = currVal;
}
else if (currVal > prevVal) {
total += (currVal - subTotal);
subTotal = 0;
}
else if (currVal < prevVal) {
total += subTotal;
subTotal = currVal;
}
else if (currVal == prevVal) {
subTotal += currVal;
}
prevVal = currVal;
}
}
total += subTotal;
return total;
}
public static int valueOf(char c)
{
if (c == 'M')
return 1000;
if (c == 'D')
return 500;
if (c == 'C')
return 100;
if (c == 'L')
return 50;
if (c == 'X')
return 10;
if (c == 'V')
return 5;
if (c == 'I')
return 1;
return 0;
}
EDIT 1:
Explanation for "IVX" value:
"...add values together except when a value (or runs of the SAME
values) is followed by a greater value, you subtract the total of that
run of values."
IVX = 1 5 10
if 5 > 1 then 5 - 1 = 4
if 10 > 5 then 10 - 0(*) = 10 (*) we already have used V(5) before, so we discard it.
So the answer for IVX is 14!
My approach would be to break the problem into the following steps:
Create a map of the symbols and values (a roman map).
Create a store to keep your result.
Loop through all the strings from RTL.
For each symbol, check that the value of the current symbol is greater than its previous value.
If the current symbol is greater than its previous value (e.g IV, where V is the current symbol), then do subtraction (current value minus previous value) and add that to the result; then skip the previous value in the loop.
Else; add the value of the current symbol to the result.
Note:
An important rule to note is that there can only be 1 prev value in the roman numerals to indicate a reduction.
IV = 4
IIV = invalid
...same with the rest of the numerals (IXCVDM...).
Hope this helps someone in the future.
class Solution(object):
def romanToInt(self, s):
"""
:type s: str
:rtype: int
"""
romanMap = { "I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000 }
result = 0;
index = len(s) - 1;
while (index >= 0):
romanValue = s[index];
prevValue = s[index - 1];
if ((index > 0) and (romanMap[romanValue] > romanMap[prevValue])):
result += romanMap[romanValue] - romanMap[prevValue];
index-= 1;
else:
result += romanMap[romanValue];
index-= 1;
return result;
You can run the code with the following:
print(Solution().romanToInt("LVIII"));
this kind of problematics are usually really easy to solve using recursive way of thinking. The solution could look like :
public int rom2int(String s)
{
if(s.length() == 0)
// no string --> 0
return 0;
else if(s.length() == 1)
// One Character --> Value of Character
return valueOf(s.charAt(0));
else if((valueOf(s.charAt(0)) > valueOf(s.charAt(1))) )
// The value is NOT followed by a greater value --> We had the value
return rom2int(s.substring(1, s.length())) + valueOf(s.charAt(0));
else if(valueOf(s.charAt(0)) <= valueOf(s.charAt(1)) )
// The value is followed by a greater (or same) value --> We substract the value
return rom2int(s.substring(1, s.length())) - valueOf(s.charAt(0));
else
// Shouldn't Happen. 0 as neutral element in in a Sum.
return 0;
}
Even if recursive solution is forbidden, to my mind it is simpler to un-recursive this algorithm than find the procedural one at first try =)
Edit :
MY Results :
Value of MCCMIIX is : 1808
Value of IIX is : 8
Value of IVX is : 4
Value of IIVVL is : 38
I want to find the sum of numbers that is divisible by x using recursive method
Ex if n= 10, x=3, the code should return sum of 3+6+9
Write a recursive method sumDivByX(n, x), which finds the sum of all
numbers from 0 to n that are divisible by x.
I asked my teacher about it and he told me "Firstly, total should be global. You should return 0 if n or x == 0. I only care if n is divisible by x. So I only add n to total (total+=n) if (n%x==0) otherwise do nothing. And do recursion sumDivByX(n-1,x) and return total as usual." I tried to correct it.
public static int sumDivByX(int n, int x) {
int total = 0;
if (n == 0 || x == 0) {
return -1;
}
if (n % x >= 1) {
return total = 0;
} else if (n % x == 0) {
return total += n;
}
return total + sumDivByX(n - 1, x);
}
When I run the program I get 0.
Eliminate the returns inside your second and third if statements
public static int sumDivByX(int n, int x) {
int total = 0;
if (n == 0 || x == 0) {
return 0;
}
if (n % x >= 1) {
total = 0;
} else if (n % x == 0) {
total += n;
}
return total + sumDivByX(n - 1, x);
}
For a cuter, more compact version
public static int sumDivByX(int n, int x) {
if (n == 0 || x == 0) {
return 0;
}
return (n % x == 0 ? n : 0) + sumDivByX(n - 1, x);
}
Note - depending on the semantics you intend, you might want to have separate checks for x<=0 (possibly and error?) and n==0 (base case).
Step through your code and you'll see that it never recurses when n ==10 and x==3, since (10 % 3 == 1)
When a method gets to a "return" statement it ends, in your case at the second if.
Your total is initialized by 0 everytime the method runs, so you should consider making it global.
Your method generates an exception if you try to use negative numbers as paramethers
Try this:
int total=0;
public static int subDivByX(int n, int X) {
if (n>0 && x>0) {
if (n%x==0){
total += n;
}
return sumDivByX(n-1,x);
}
else return -1;
}
This seems to work
private static int sumDivByX(int n,int x) {
if (n < x || x < 1 ) {
return 0;
}
int d = n/x;
return (x * d) + sumDivByX(n - x , x);
}
Recursion could cause a stackoverflow.