changing the order of condition in while loop crashes the program - java

changing the order of condition in while loop crashes the program. If I write like: while(a[in-1]>=temp && in>0), the program wont work. Why? The error is:ArrayIndexOutOfBoundsException: -1. The code below works until i make the above change.
public class ISort {
public int[] sort(int[] a){
int n=a.length;
for(int out=1;out<n;out++){
int temp=a[out];
int in=out;
while(in>0 && a[in-1]>=temp ){
a[in]=a[in-1];
in--;
}
a[in]=temp;
}
return a;
}
public static void main(String[] args){
int[] a={3,2,1,6,3,8,8,10,9};
ISort s=new ISort();
int[] res=s.sort(a);
for(int i=0;i<res.length;i++ ){
System.out.print(" "+res[i]+" ");
}
}
}

Because of Short-circuit evaluation.
If you write while(in>0 && a[in-1]>=temp), then if in <= 0, you don't evaluate the second part.
Why?
Because the result of false && anything is always false, so it's redundant to check the other side if the first side is already evaluated to false.
I think you got AarrayIndexOutOfBoundsException when you changed the order because in was <= 0 and you still tried to access a in a negative index. That's why when you want to access a method via some object and you're not sure whether the object is null, you sometimes do:
if(myVar != null && myVar.myMethod())

Because if in becomes 0 then in - 1 will be -1 and which is invalid index for array.
while(in>0 && a[in-1]>=temp) works because
When in > 0 is evaluated to false then due to short circuit a[in - 1] >=temp is not evaluated
while(a[in-1]>=temp && in>0) doesnt because
first a[in - 1] will be evaluated and when in reaches to 0 then in - 1 will be -1 and that will throw exception as -1 is not a valid index for an array and will throw ArrayIndexOutOfBoundsException.

Reason of not work of condition is that while(a[in-1]>=temp && i>0) array got negative index at in=0.

Consider the case where in = 0. The first thing the will be evaluated is a[in - 1] = a[-1] = IndexOutOfBounds. By checking the value of in first, you abort checking the array index if in is not greater than 0.

Related

Beginner Boolean compiling error

I am very new to Java (doing a beginners university module) so sorry for the probably silly question. I am trying to verify whether a ragged array is a 'tridiagonal matrix'.
It is valid if it is of length 3 at the first level and of length n − 1, n, and n − 1 at the second level. I intended to come up with a code to firstly verify the length is 3, then find the longest length array within it for n, then finally verify each length.
For whatever reason my code won't compile but I'm not seeing an error message, just a red exclamation mark on the class. I assume this means there are multiple errors. If anyone could point them out it would be a massive help.
static boolean isValidTridiagonal ( double [][] m)
{
if (double [][]=new double [3][])
{
int n = 0;
for(int i = 0; i < m.length; i++)
{
if(m[i].length > n)
{
n = m[i].length;
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
{
return true
}
else
{
return false
}
}
else
{
return false
}
}
Thanks very much!
I agree with Foolish in the comments that it's helpful to use an IDE that can highlight syntax errors and other problems with the code, it really makes a huge difference. Apart from that, another general strategy is to always code in "baby steps": do only the minimal thing to test if the code works, compile and test often. And if you still have troubles, you can always comment out chunks of your code when searching for the offending bits.
Having said that, the errors that I see in your code are:
if (double [][]=new double[3][])
If you want to test the length of the input, you can do if (m.length == 3)
In
if( (m[0].length = n-1) && (m[1].length = n) &&(m[2].length=n-1))
you're not testing for equality, but rather trying to put the values n-1 etc into m[0].length, which is not going to work. What you probably meant was
if( (m[0].length == n-1) && (m[1].length == n) &&(m[2].length==n-1))
In
return true
you're missing a semicolon. The compiler is whiny about things like that and unless you use an IDE or learn to interpret the compiler error messages, it can be really painful to find such errors.
Finally, of course, the answer by vasste provides a much simpler solution to your actual task, so it's worth looking into that :).
Why do you need all that loops? If all arrays cannot be null, than
static boolean isValidTridiagonal(double[][] m) {
return m.length == 3 && m[0].length == m[1].length - 1 && m[2].length == m[0].length;
}
You're missing a few braces at the end but, judging from your indentation, you just forgot to copy them.
You're missing semicolons from the end of the return lines.
The condition within this if statement if (double [][] = new double [3][]) is not a valid expression. You simply want to evaluate the length, which you can do like if (m.length == 3). You did the same thing later on.
The line including (m[0].length = n-1) && (m[1].length = n) && (m[2].length=n-1) is not valid because you are performing assignment (=) in all three cases. An equality check is the double equals operator ==.
You do not return a value in every case. You can fix this by adding return false; after the closing brace of your first if statement, i.e. the last line of the function.
This is enough to get your code to compile. As mentioned in another answer though, your logic is confusing and without actually tracing it through I would speculate that it will not work as you would expect.
If I have understood your requirements correctly, you can rewrite the entire function as:
static boolean isValidTridiagonal ( double [][] m)
{
return m.length == 3 &&
m[0].length + 1 == m[1].length &&
m[2].length + 1 == m[1].length;
}
A proper IDE - Netbeans, Eclipse, etc. - will give you fairly descriptive error messages to show you where you've gone wrong.
This is basically completely stylistic but I wish someone had pointed this out to me earlier. If you ever find yourself writing code in this form:
if( (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1))
{
return true;
}
else
{
return false;
}
know that you can save yourself so many lines without losing any readability by instead writing:
return (m[0].length == n-1) && (m[1].length == n) && (m[2].length == n-1);

ArrayIndexOutOfBoundsException when .length is zero

I got a java.lang.ArrayIndexOutOfBoundsException and I think it is because when nums.length gives me a zero (because there is nothing inserted in the parameter) the attribute I gave to the variable (-----.length -1------) will make it -1 when it gives me zero.
How should I make it not do this knowing that if I leave it .length without a -1 there will be an out of bounds exception on the other side of the array?
public boolean sameFirstLast(int[] nums) {
int lengthOfArray = nums.length - 1;
int thisIsHowLong = nums.length;
if (nums[0] == nums[lengthOfArray ] && thisIsHowLong > 0){
return true;
}
return false;
}
//always remember to return false in the end becuse if the top dosnt run then
//there will be no boolean returned and the method is not void so it has to return a //boolean
//ALWAYS REMEMBER TO SET nums.length - 1
//the .length method always starts from 1 and threfore will give you an extra space //that it will check for but we wont have anything in that space and then the compiler //will go to that space and will fond nothing to test with and gove an ERROR out of //bounds exeption because it is looking out of the array.
Your condition should look like
if(thisIsHowLong > 0 && nums[0] == nums[lengthOfArray ] )
Now if your first condition is false, second will never be checked.
And you want same.
You need to interchange the conditions.
if (thisIsHowLong > 0 && nums[0] == nums[lengthOfArray ]){ // This will prevent the exception.

i do not understand the comparison

Im currently going over MIT courseware for java and am unsure why there is a piece of code involved. I tried removing the code to determine if it is necessary and it kept the program from running.
I have two arrays, one is names of runners, the other is their times. the goal is to find the index of the lowest (fastest) time and then also give the person with the second fastest time. i.e the command prompt will output john is the fastest and kate is the second fastest
the part i am confused about is "secondIndex == -1 ||" --- why is this here? if i remove it i get the error
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
public static int getSecondIndex(int[] values) {
int minIndex = getMinIndex(values);
int secondIndex = -1;
for(int i = 0; i < values.length; i++) {
if(i == minIndex){
continue;
}
if(secondIndex == -1 ||
values[i] < values[secondIndex]) {
secondIndex = i;
}
}
return secondIndex;
}
It will then evaluate values[secondIndex] which does not have an entry at index -1. The || short circuits from left to right so in the case of secondIndex = -1, values[secondIndex] will never be evaluated.
It's because the loop checks if the current runner's time is less than any time found so far, but when it checks the first runner there is no "fastest runner so far" to compare to. So the check first makes sure that secondIndex has been set at least once before. If it hasn't, the second part of the or statement will never get evaluated (called short-circuit evaluation).
The reason it's there is because of how indexOf works: it can only find things that live on index 0 or higher, so if it cannot find anything, it returns -1.
As such, we compare to -1 to see whether or not something was found at all. If it wasn't, we don't need to waste any more time on it:
if(thing.indexOf(otherthing) == -1) {
// the search failed
}
if it was, we can use the result to immediately look it by using the result of indexOf as an array index.
This condition (secondIndex == -1) is true in the case that secondIndex has not yet been found. Remember that since || is a short circuit operator, if the first condition is true, the second one will not be evaluated. Therefore, if secondIndex is -1, values[secondIndex] will never be evaluated (which is good, because doing so would cause the ArrayIndexOutOfBoundsException).

In an array with null spaces, how can consolidate all of the non null values together?

Hey so I have this homework assignment and I'm having issues with one of the methods. I would like hints and not actual answers/code.
So I have a class called HorseBarn that messes with an array of horses(horse being the type). My problem is I'm having troubles with the consolidate method.
What the array would look like before consolidate:
a,b,c,d are horses
|a|null|b|null|c|d|
What the array would look like after consolidate:
|a|b|c|d|null|null|
So my logic would be to make a nested for loop. The first loop would search for a null value, once the first loop finds the null value, the second loop would look for a horse and then swap with it. Then the second loop would end and go back to the first loop. So here is what I have right now and it doesn't work(it just terminates). Is my logic wrong or is it my syntax that's causing the problems?
public void consolidate()
{
int j = 0;
for(int i = 0; i < spaces.length;i++)
{
if( spaces[i] == null)
{
for(j = i; j < spaces.length && spaces[j] == null; j++)
{
}
spaces[i] = spaces[j];
spaces[j] = null;
}
}
Well for starters, this should give an index out of bounds exception if the last non-null is found and there still are elements remaining:
ex: horses = | a | null | null | null |
for i = 1, since horses[1] -> horses[3] are empty, j first gets set to 1 then ends with j = 4 (because of the termination condition j < horses.length())
You would then try to swap horses[1] with horses[4], which throws the array index out of bounds
In the inner for loop, just find the position of next non null value and break it there.
Then swap it with your null.
A better time efficient code.

Can't figure out why recursion never resolves

My friend is making a minesweeper clone and he asked me to help with the part where when you click on a non-mine/non-number 'blank' square it reveals all adjacent blanks. The following is the code I wrote. I can't figure out why it never resolves.
My base case should be when the for loops completely execute and the if statement never returns true.
Is there something I'm missing?
This is in java, by the way. Also, I told him the whole slew of button state changing should be assigned to a method :p
public void revealAdjacentNulls(int r, int c)
{
int ir, ic;
//literal edge cases :P
int rmax = (r == 15) ? r : r + 1;
int cmax = (c == 15) ? c : c + 1;
//check all spaces around button at r,c
for(ir = (r==0) ? 0 : r-1; ir <= rmax; ir++){
for (ic = (c==0) ? 0 : c-1; ic <= cmax; ic++){
//if any are blank and uncovered, reveal them, then check again around the blanks
if (buttons[ir][ic].value == 0 && buttons[ir][ic].isCovered == false)
{
buttons[ir][ic].setEnabled(false); //number uncovered
buttons[ir][ic].setBackground(Color.blue);
buttons[ir][ic].setText(Character.toString(buttons[ir][ic].value));
buttons[ir][ic].isCovered = false;
revealAdjacentNulls(ir, ic);
}
}
}
}
Let's consider the case when r==0 and c==0, and let's assume that buttons[0][0].value == 0 and that buttons[0][0].isCovered == false.
The very first iteration of the loop will cause the function to call itself with the same arguments, 0, 0, and with unchanged state of value and isCovered. This will instantly lead to infinite recursion.
P.S. Check out the Wikipedia article for other flood fill algorithms.
Well for one thing, it will always keep recursing for revealAdjacentNulls(r, c). Your condition is that isCovered must be false - but then you're setting isCovered to false as well. Did you mean to write:
buttons[ir][ic].isCovered = true;
? Or possibly your check should be:
if (buttons[ir][ic].value == 0 && buttons[ir][ic].isCovered)
(It depends on what you mean by "is covered".)
Another case: if r == 15 then the loop will be from 14 (r - 1) to 15 (rmax). If your if statement is true, then there will be infinite recursion. The same applies to c.

Categories