This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 3 years ago.
I wrote in an exam a backtracking code that moving between cell and counting paths, the conditions are if the next cell is i+k or j+k or i-k or j-k.
the code somehow is still going out of bounds even due I tried to prevent it from doing so.
I tried adding fixing the code by adding +1 in the checking valid move in the "if" conditions.
public class Test3
{
public static int howManyPaths(int [][] mat)
{
return howManyPaths(mat,0,0,0);
}
private static int howManyPaths(int [][] mat, int i, int j, int count)
{
if(i == mat.length-1){return count;}
if(j == mat[i].length-1){return howManyPaths(mat,i+1,0,count);}
count = pathCount(mat,i,j);
return howManyPaths(mat,i,j+1,count);
}
private static int pathCount(int [][] mat, int i, int j)
{
int k = mat[i][j];
if(i < mat.length-1 && mat[i][j] == mat[i+k][j] && i+k < mat.length-1){
return 1 + pathCount(mat,i+k,j);}
if(j < mat[i].length-1 && mat[i][j]==mat[i][j+k] && j+k < mat[i].length-1){
return 1 + pathCount(mat,i,j+k);}
if(i > 0 && mat[i][j]==mat[i-k][j] && i-k > 0){
return 1 + pathCount(mat,i-k,j);}
if(j > 0 && mat[i][j]==mat[i][j-k] && j-k > 0){
return 1 + pathCount(mat,i,j-k);}
return 1;
}
}
the expected is how many paths and the actual results are "out of bounds".
Edited with the fixet code still not working
In your code,
if(i < mat.length-1 && mat[i][j] == mat[i+k][j]){
return 1 + pathCount(mat,i+k,j);}
what will it be, if i+k>=mat.length? Or,
if(j < mat[i].length-1 && mat[i][j]==mat[i][j+k]+1){
return 1 + pathCount(mat,i,j+k);
what will it be, if j+k>=mat[i].length? Or,
if(i > 0 && mat[i][j]==mat[i-k][j]){
return 1 + pathCount(mat,i-k,j);}
what will it be, if i-k<0? Or,
if(j > 0 && mat[i][j]==mat[i][j-k]){
return 1 + pathCount(mat,i,j-k);}
what will it be, if j-k<0?
Handle these cases as well. See, being i>0, still i-k can be less than or equal to 0. This is the trick in your case.
Hope you got it now.
Edit:
After you editing your code still it is getting the same exception as you are accessing the indexes and then checking if the index is a valid one.
Not this:
if(i < mat.length-1 && mat[i][j] == mat[i+k][j] && i+k < mat.length-1)
Instead, you must write:
if(i < mat.length-1 && i+k < mat.length-1 && mat[i][j] == mat[i+k][j])
Same for others as well.
By doing this, you will be able to get rid of java.lang.ArrayIndexOutOfBoundsException
Related
This question already has answers here:
How do you get absolute values and square roots
(6 answers)
Check if int is between two numbers
(11 answers)
Closed 1 year ago.
I am new to JAVA, and I have a question about one of the practice assignments.
The question is:
Given an int n, return true if it is within 10 of 100 or 200.
Why do the codes below have errors (bad operand types for binary operator '<=' or '<')?
public boolean nearHundred(int n) {
return (90 <= n <= 110) || (190 <= n <= 210);
}
public boolean nearHundred(int n) {
return (89 < n < 111) || (189 < n < 211);
}
I finally figured out the solution, but I was wondering if there is a better solution for the "absolute" value.
public boolean nearHundred(int n) {
if(n <= 100){
return (100-n)<=10;
}
if (n>=100 && n <= 200){
return (n-100) <=10 || (200-n) <=10;
}
if (n > 200){
return (n-200)<=10;
} else {
return false;
}
}
Thank you very much for your help!
add &&s between your operations so switch return (90 <= n <= 110) || (190 <= n <= 210);
to something like
return (90 <= n && n <= 110) || (190 <= n && n <= 210);
(you can't change operations like that)
Java cannot chain logical operations like a > b > c. You need to use && to connect two parts.
90 <= n && n <= 110 || 190 <= n && n <= 210
"and" is executed before "or", you don't need parenthesis, but you can add them for readability.
(90 <= n && n <= 110) || (190 <= n && n <= 210)
In you case you can also get the absolute value after subtraction:
Math.abs(100 - n) <= 10 || Math.abs(200 - n) <= 10
Alternately you can use Range class from the Guava library:
Range.closed(90, 110).contains(n) || Range.closed(190, 210).contains(n)
Apache Commons Lang has a similar class as well.
You can try Math.abs()
The java.lang.Math.abs(int a) returns the absolute value of an int value
Reference: https://www.tutorialspoint.com/java/lang/math_abs_int.htm
You can use the Range class:
Range<Integer> lowerRange = Range.between(90,110);
Range<Integer> upperRange = Range.between(190,210);
return lowerRange.contains(n) || upperRange.contains(n);
I am making a program that checks to see if an elements positive and negative charges are able to combine to make 0. A thing i want to do is output the reasons why the two elements are not able to combine. But it is more difficult than i expected. for example if sodium were trying to combine with copernicium, it would output this:
Sodium doesn't combine with Copernicium:
Both valence charges have same polarity.
One or more elements is man-made.
but i can not think of a way to implement this into my code.
here is my code:
public void combine(Element element){
if ((element.getValence() > 0 && valence < 0) || (element.getValence() < 0 && valence > 0)) { //one element needs a positive valence, and one needs a negative valence
if (valence != 0 && element.getValence() != 0) { //checks to see if valence is not equal to 0
if (natural == true && element.isNatural() == true) { //checks to see if both elements are natural
for (int x = 1; x <= 4; x++) {//bruteforce the atoms to see if they both add up to 0.
for (int y = 1; y <= 4; y++) {
if ((valence * x) + (element.getValence() * y) == 0) {
System.out.println(name + " combines with " + element.getName() + " to form " + symbol + "" + x + "" + element.getSymbol() + "" + y);
}
}
}
}
}
}
}
Thanks for any help!
The way to do this is to add else clauses for each if that return an appropriate message.
if ((element.getValence() > 0 && valence < 0) || (element.getValence() < 0 && valence > 0)) { //one element needs a positive valence, and one needs a negative valence
{
// the inner tests
}
else
{
System.out.println("The elements are both positive or both negative");
}
}
This should get you started in the right direction.
This question already has answers here:
Java error: Comparison method violates its general contract
(13 answers)
Closed 7 years ago.
Edit: why I think this is not a duplicate: As biziclop wrote, the problem here is not intransitivity (a>b & b>c => a>c) as in the other problems mentioned here, but that the clause a>b => -(b>a) is violated, so it's a different problem.
I am receiving the following error message:
Exception in thread "main" java.lang.IllegalArgumentException: Comparison method violates its general contract!
at java.util.TimSort.mergeHi(Unknown Source)
at java.util.TimSort.mergeAt(Unknown Source)
at java.util.TimSort.mergeForceCollapse(Unknown Source)
at java.util.TimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at construct.Repair.regretRepair(Repair.java:101)
at lns.One.repaired(One.java:122)
at lns.One.segment(One.java:68)
at lns.One.lnsSolution(One.java:35)
at lns.All.lnsSolutions(All.java:22)
at barter.Genetic.initialPopulation(Genetic.java:36)
at barter.Genetic.run(Genetic.java:26)
at program.Main.main(Main.java:22)
This is where it happens:
Arrays.sort(regretProfits, new Comparator<RegretProfit>(){
#Override
public int compare(RegretProfit first, RegretProfit second){
if (first.possibleRoutes <= 0){
if (second.possibleRoutes > 0){
return 1;
}
return 0;
}
if (first.possibleRoutes < solution.schedule.size() - kay + 1){
if (first.possibleRoutes < second.possibleRoutes){
return -1;
}
if (first.possibleRoutes > second.possibleRoutes){
return 1;
}
if (first.profit > second.profit){
return -1;
}
if (first.profit < second.profit){
return 1;
}
}
if (first.regret > second.regret){
return -1;
}
if (first.regret < second.regret){
return 1;
}
return 0;
}
;});
And this is the class where the object RegretProfit is defined:
public class RegretProfit {
public int[] order;
public double regret;
public double profit;
public int possibleRoutes;
}
The error occurs only every few thousand iterations. I would be really thankful if anybody had some ideas what the problem might be. I've read that intransitivity can cause this exception but I really couldn't figure out where I possibly went wrong.
Solved it, thanks to biziclop!
Arrays.sort(regretProfits, new Comparator<RegretProfit>(){
#Override
public int compare(RegretProfit first, RegretProfit second){
if (first.possibleRoutes <= 0 && second.possibleRoutes > 0){
return 1;
}
if (first.possibleRoutes <= 0 && second.possibleRoutes <= 0){
return 0;
}
if (first.possibleRoutes > 0 && second.possibleRoutes <= 0){
return -1;
}
if (first.possibleRoutes < solution.schedule.size() - kay + 1 || second.possibleRoutes < solution.schedule.size() - kay + 1){
if (first.possibleRoutes < second.possibleRoutes){
return -1;
}
if (first.possibleRoutes > second.possibleRoutes){
return 1;
}
if (first.profit > second.profit){
return -1;
}
if (first.profit < second.profit){
return 1;
}
}
if (first.regret > second.regret){
return -1;
}
if (first.regret < second.regret){
return 1;
}
return 0;
}
;});
It isn't transitivity that is the key problem here, the part of the contract violated is sgn(compare(x, y)) == -sgn(compare(y, x))
If you have these records for example:
first.possibleRoutes = -1; first.regret = 1
second.possibleRoutes = 1; second.regret = -1
Your comparator returns 1. But if you swap them:
first.possibleRoutes = 1; first.regret = -1
second.possibleRoutes = -1; second.regret = 1
Your comparator still possibly returns 1.
Looking at the code there are two suspicious, non-symmetric constructs:
if (first.possibleRoutes <= 0){
if (second.possibleRoutes > 0){
return 1;
}
return 0;
}
Here there's no matching -1 return if first and second are reversed. You also treat every item with possibleRoutes <= 0 as equal, which is probably not what you want.
if (first.possibleRoutes < solution.schedule.size() - kay + 1){
Here you enter a branch based purely on the value of first, which means this branch can also potentially lead to sgn(compare(x, y)) != -sgn(compare(y, x)).
Of course it is possible that under the additional constraints of the full system the two problems cancel each other out (clearly they don't in this case), but it's a very brittle way of designing comparators and I'd advise you to make sure that all branches are symmetrical. It makes it a lot easier to reason about the correctness of your code.
I took a programming class, and I'm revisiting old programs that I did not quite get right. This one is a Game Of Life program, and I have a question about code cleanup.
I need to make sure that an array element is in bounds before checking whether its neighbor's boolean value is true or false. I have a statement to check if firstGen[0][0]'s top-left (up one row, left one column) is in bounds. Is there an easier or more elegant way to check if an element is in bounds or to restrict the element checks to the boundaries of a given array without using four && conditionals per if statement?
Note that I have only changed the first if statement thus far, so there may be errors elsewhere. I also excluded the boundary checks for the other neighbors.
public static boolean[][] generation(boolean[][] firstGen)
{
int length = firstGen.length;
boolean[][] newGen = new boolean[length][length];
for (int j = 0; j < firstGen[0].length; j++)
{ for (int i = 1; i < firstGen.length; i++)
{
int count = 0;
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
if ((newGen[i][j] == false) && (count == 3)) newGen[i][j] = true;
else if ((newGen[i][j] == true) && (count == 1)) newGen[i][j] = false;
else if ((newGen[i][j] == true) && (count > 3)) newGen[i][j] = false;
else break;
}
}
return newGen;
}
If i and j are in bounds, then you know for sure that i - 1 < length and j - 1 < length are both true.
Also:
i - 1 >= 0 can be written i > 0
if (condition == true) can be rewritten if (cond)
So you could replace:
if ((i-1 >= 0) && (i-1 < length) && (j-1 >= 0) && (j-1 < length)) //top-left element exists
{ if (newGen[i-1][j-1] == true) count++; } //increment `count` if top-left element is true
by:
//increment `count` if top-left element is true
if (i > 0 && j > 0 && newGen[i-1][j-1]) count++;
That's the best way I can think of to check if its out of bounds, but an alternative method in general, and one that I think gives programs like the Game of Life more exciting outcomes, is adding periodic boundaries. Basically this means that if you walk off one edge, you end up on the other side (like in pac-man). It sounds complicated, but really all it takes is the % function, which returns the remainder of division between the two numbers given.
So:
27 % 5 = 2;
So for adding periodic boundries you would update x and y positions like this:
x = (x + xStep + horizontalSize) % horizontalSize;
y = (y + yStep + verticalSize) % verticalSize;
Where xStep and yStep are +1 or -1 depending on what direction you want to go. (this works nicely with a for loop) The addition of the size is to make sure you go below zero when you get close to borders.
Then you never have to worry about messy border conditions, everything simply overlaps. No need to check each and every border. I hope this makes sense. Please ask for clarification if not. I've used this more for random walker programs but the idea is the same.
I seem to get an error when I test running my program, which says java.lang.ArrayIndexOutOfBoundsException: -1
Please can anyone give me some advice on how to fix this?
class MineFinderModel {
public static int MINE_SQUARE = 10;
public static int EMPTY_SQUARE = 0;
int num_of_cols;
int num_of_rows;
int[][] the_minefield;
public MineFinderModel(int n_cols, int n_rows) {
num_of_rows = n_rows;
num_of_cols = n_cols;
the_minefield = new int[num_of_cols][num_of_rows];
}
public boolean addMine(int thisCol, int thisRow) {
if (thisCol >= num_of_cols || thisRow >= num_of_rows)
return false;
if (the_minefield[thisCol][thisRow] == MINE_SQUARE)
return false;
the_minefield[thisCol][thisRow] = MINE_SQUARE;
return true;
}
public int getValue(int thisCol, int thisRow) {
if (thisCol >= num_of_cols || thisRow >= num_of_rows)
return 0;
return the_minefield[thisCol][thisRow];
}
public void addMinesToCorners() {
the_minefield[0][0] = MINE_SQUARE;
the_minefield[0][num_of_rows -1] = MINE_SQUARE;
the_minefield[num_of_cols - 1][0] = MINE_SQUARE;
the_minefield[num_of_cols - 1][num_of_rows - 1] = MINE_SQUARE;
}
}
I guess that it should be in the "addMinesToCorners()" function since you are not testing the boundaries.
What about trying to put some if around you variables ?
if(num_of_cols == 0)
if(num_of_rows == 0)
At initialization, this equals "0", and then "0 - 1" gives "-1". Hence the error.
Hope this helps !
All your methods have the max value check but none of them are checking for a negative value in thisRow and thisCol so the addMine() and getValue() will throw an java.lang.ArrayIndexOutOfBoundsException if any of the arguments to these 2 methods is negative.
You can add a condition like
`
if (thisCol >= num_of_cols || thisCol < 0
|| thisRow >= num_of_rows || thisRow <0)
return false
Arrays are zero indexed so your checks are incorrect, e.g., if num_of_cols is 10 then the last position will be 9 but your check will pass if you pass in 10 as thisCol because it is checking against the initialiser value instead of the length of the array.
Try changing your test to
if (thisCol < 0 thisCol >= (num_of_cols - 1) || thisRow < 0 || thisRow >= num_of_rows - 1))