I have 2 for loops, I am working on a 2048 like game. This method returns true if something slid to the left. However, it returns false to me and only "banana" is printing, which means the other for loop isn't even executed. What could be the case?
public boolean slideLeft(int[][] array, int row) {
int[] array2 = new int[array.length];
boolean result = false;
for(int j = 0; j < array.length; j++) {
array2[j] = array[j][row];
System.out.println("banana");
}
for (int i = 0; i <array2.length; i ++) {
if (array2[i] == 0 && array2[i+1] != 0 && i != array2.length-1) {
System.out.println("apple");
array2[i] = array2 [i+1];
result = true;
}
if(array2[i] != 0 && i != 0 && array2[i-1] == array2[i]) {
System.out.println("pear");
array2[i-1] = 2*(array2[i-1]);
array2[i]=0;
result = true;
}
}
return result;
}
Second for loop executed but none of condition inside the second for loop is not match. Then you will not get any out put.
You can make sure second for loop is running just put a else and print something.
You need to reconsider and rethink about condition inside the second for loop to correct them.
Your other for loop would throw ArrayIndexOutOfBoundsException when i==array2.length-1, because the following condition is evaluated from left to right, so array2[i+1] would be aveluated before i != array2.length-1 is evaluated.
if (array2[i] == 0 && array2[i+1] != 0 && i != array2.length-1) {
System.out.println("apple");
array2[i] = array2 [i+1];
result = true;
}
You should change it to :
if ( i != array2.length-1 & array2[i] == 0 && array2[i+1] != 0) {
System.out.println("apple");
array2[i] = array2 [i+1];
result = true;
}
Your second if condition avoids a similar exception, since you check that i != 0 before checking that array2[i-1] == array2[i].
Its seems that you are trying to create an array, array2, of integers of length array.length. There is a possibility that the array.length could just contain two rows (possibility of single row is eliminated because if there was just one row you would have seen IndexOutofBoundException) in such case your if conditions will never get executed.
A way you can work through is by placing check statements for array.length and else clause in the second for loop.
Related
public static void insertionSort(int[] data) {
for (int i =0; i < data.length; i++) {
int current = data[i];
int j = i-1;
while (j >=0 && data[j] >= current) {
data[j+1] = data[j];
j--;
}
data[j+1] = current;
}
}
the line while (j >=0 && data[j] >= current) should throw array index of bounds when data[-1] for the first time. I dont understand why it does not. Can some one please help
Thank you
Ashok Pappu
Boolean expressions like these are never fully evaluated if the condition can be met earlier.
So...in your case since j >= 0 is false and false && ??? will always be false the second part does not need to get evaluated. This is why data[-1] will never be called.
You can use the same principle for null checks, e.g.
if (object != null && object.isSomething())
If while clause contains more, than 1 expression, splitted by &&, they are executed one by one. This is done to increase performance.
I.e. at first in your code j >= 0 will checks. If j < 0, it false. So, cycle will be interrupted regardless of the 2nd expression.
I want to know how many zeros are between sequential non-zero elements in f array. This is how I do it:
int[] f = new int[]{0,0,3,0,0,1};
int start = 0, end = 0;
for (int i=0; i<f.length; i++)
{
if (f[i] != 0 && start == 0)
start=i;
else if (f[i] != 0 && start != 0)
end=i;
}
int cnt = (end-start-1)>=0 ? (end-start-1) : (start-end-1);
The answer is 2 zeros between 3 and 1.
However, in case of int[] f = new int[]{0,3,2,0,0,1} the answer is 3, which is not correct. It should be 2.
Update:
I want to count the number of zeros between LAST left-hand side non-zero element and FIRST right-hand side non-zero element.
Your logic of detecting when there are changes (from 0 to non-0 and from non-0 to 0 elements) is flawed.
You should look at the i and i-1 elements instead. Consider the following:
The start index should be when element i-1 is non-zero and element i is 0.
The end index should be when element i-1 is 0 and element i is non-0 and a start element was found (start > 0, this is to take into account the fact that the array can start with 0 and there were no start sequence).
The next thing to consider is that there may be multiple cases of 0's enclosed in non-0's in the array so each time we encounter an end element, we need to add this to a current count.
Putting this into code:
private static int countZeros(int[] f) {
int start = 0, end = 0, cnt = 0;
for (int i = 1; i < f.length; i++) {
if (f[i-1] != 0 && f[i] == 0) {
start = i;
} else if (f[i-1] == 0 && f[i] != 0 && start > 0) {
end = i;
cnt += end - start;
}
}
return cnt;
}
Some examples:
System.out.println(countZeros(new int[]{0,0,3,0,0,1})); // prints 2
System.out.println(countZeros(new int[]{3,0,0,1})); // prints 2
System.out.println(countZeros(new int[]{3,0,0,1,0})); // prints 2
System.out.println(countZeros(new int[]{3,0,0,1,0,1})); // prints 3
If you want the last 0s group, count backwards.
private static int countZeros(int[] f) {
for (int i=f.length-1; i>=0; i--){
if(f[i]!=0 && i>0 && f[i-1]==0){
i--;
int count=0;
while(i>=0 && f[i]==0){
i--;
count++;
}
if(i==0)
return null;
else
return count;
}
}
return null;
}
Your loops behaviour will have the following effect:
for (int i=0; i<f.length; i++)
{
if (f[i] != 0 && start == 0) //finds only first non-zero in whole array
start=i;
else if (f[i] != 0 && start != 0) //finds last non-zero in whole array
end=i;
}
But by taking the difference you include all non-zeros and zeros in the range. So you need a way to count only zeros between these to points, which is hard to add to the first loop because end will be changing. The easiest solution is to loop a second time from start to end and count the zeros:
int cnt = 0;
for(int i=start; i<end; i++)
if(f[i]==0)
cnt++;
This may not the most efficient solution, but it is a way to build upon your existing logic.
How to manipulate the for loop, the question is on the comments
How to re-enter the for loop and adding the index dynamically except for the auto increment.
for (int i = 0; i < words.size(); i++)
{
try {
temp = QueryWithContext.query(words.get(i));
if((temp == null || temp.isEmpty()) && words.size() > i+1)
{
QueryWithContext.query(words.get(i)+" "+words.get(i+1));
temp = QueryWithContext.query(words.get(i)+" "+words.get(i+1));
System.out.println("1st if");
//if condition = true, the codes below must not run anymore
//and for loop will increment by 1 except for the auto inc
if((temp == null || temp.isEmpty()) && words.size() > i+2)
{
System.out.println("2nd if");
temp = QueryWithContext.query(words.get(i)+" "+
words.get(i+1)+" "+words.get(i+2));
//if condition = for loop will increment by 2
//except for the auto inc
}
}
}
}
If you meant increasing the loop index, then you can increase the i value that represents the index. i += 2; should do the work. It will eventually increase it by 3 when the loop ends and starts over.
This method is supposed to return true if there is more than one 1 in a column of a 2D array, yet it doesn't work. I can't figure out what's wrong with it so I thought I'd get some expert opinions.
Example:
10010
01001
10100
will return true because there are 2 ones in the first column.
Here is the code
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
boolean break2 = false;
boolean check = false; //false means no 2 (or more) queens in same column
for (int i = 0; i < x.length; i++) {
count = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
count++;
}
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
}
return check;
}
You break at the first occurance of 1 in whole array, which is probably not the expected result.
Explanation of how your code works:
loop until counter i is less than length of array (number of rows in array)
loop until counter j is less than length of i-th row (number of columns or elements in array)
check if element on i-th row and j-th column is 1, if true, increase variable count by one
if count is greater than 1 (this means it has to be 2 or greater) set break2 and check to true, break
if break2 is true (which is as count is > 2 and first loop breaks), break this loop too:
this happens in 1st row of your example table
end of loops, return check (which is true because 1st row contains 2 ones)
The problem in your code is that you break when you find your first row that satisfies your condition, but you do not (necessarily) check all the rows in given array.
I have corrected the code for you, hopefully it works (untested)
public static boolean isVert(int[][] x) { //checks for more than one 1 in columns
int count = 0;
for (int i = 0; i < x.length; i++) {
int rowCount = 0;
for (int j = 0; j < x[i].length; j++) {
if (x[i][j] == 1) {
rowCount++;
}
if(rowCount > 1) {
count++;
break;
}
}
}
// returns true if count of lines containing 1 equals length of array,
// if not, returns false
return count == x.length;
}
Start of by improving your naming convention. Your code has many variables named by their contents, instead of named by how they are used. For example:
boolean check = false; // false means no two queens in the same column.
instead of
boolean twoQueensInColumn = false;
and the other example
boolean break2 = false;
instead of the more reasonable
boolean continueLooking = true;
Plus, it is a very good idea to avoid using variables as place holders for loop escaping logic. For example, the two stanzas
...
if (count > 1) {
break2 = true;
check = true;
break;
}
}
if (break2) {
break;
}
are a breeding ground for bugs, requiring a lot of debugging to ensure they work "right now" which will break just as soon as you modify the code. Much better would be
boolean keepLooking = false;
for (int row = 0; keepLooking && (row < board.length); row++) {
int queensInColumn = 0;
for (int column = 0; keepLooking && (column < board[row].length, column++) {
if (board[row][column] != 0) {
queensInColumn++;
}
if (queensInColumn > 1) {
keepLooking = false;
}
}
}
The main difference being the control logic is in the loop "conditional" block, where it belongs.
I would recommend turning your integers to string and using the .contains() method and looping through that. This would make the code easier to understand.
This is an interview question. I think the code below, works a bit and has some errors. The problem is as follows -
In 1-9 keypad one key is not working. If some one enters a password then not working key will not be entered. You have given expected password and entered password. Check that entered password is valid or not
Ex: entered 164, expected 18684 (you need to take care as when u enter 18684 and 164 only both will be taken as 164 input)
The code which does above is below.
public static void main(String[] args){
System.out.println(IsAMatch("164","18684"));
}
static boolean IsAMatch(String actual, String expected)
{
char faultyKey = '\0';
int i = 0, j = 0;
for(; i < expected.length() && j < actual.length(); ++i)
{
if(actual.charAt(j) != expected.charAt(i))
{
if('\0' != faultyKey){
if(faultyKey != expected.charAt(i))
return false;
}
else{
faultyKey = expected.charAt(i);
}
}
else{
++j;
}
}
System.out.println("FaultyKey= "+faultyKey);
return (i == expected.length() - 1 && j == actual.length() - 1)? true : false;
}
It is detecting the faulty key correctly (Ex here it is 8), but giving wrong output (As False) Even though the test case used above should give true.
Any suggestions to fix this? If any better method/ideas are most appreciated.
Change the return statement to:
return (i == expected.length() && j == actual.length())? true : false;
The bug is that i and j are both increased first and then checked if they meet the loop condition. Obviously both i and j fail to meet the condition as the control flow breaks out from the loop. Therefore, i and j are exactly equal to expected and actual length respectively.
Moreover, the expression in your return statement is gratuitous. You could just return true at that point of the program as it is a tautology at that stage. I.e. there is no way that you can be at that point in your code and your expression evaluates to false.
static boolean IsAMatch(String actual, String expected) {
char faultyKey = '\0';
int i = 0, j = 0;
for (; i < expected.length(); ++i) {
if (j >= actual.length() || actual.charAt(j) != expected.charAt(i)) {
if ('\0' != faultyKey) {
if (faultyKey != expected.charAt(i)) {
return false;
}
} else {
faultyKey = expected.charAt(i);
}
} else {
++j;
}
}
System.out.println("FaultyKey= " + faultyKey);
return (i == expected.length() && j == actual.length()) ? true : false;
}
Consider the following condition
System.out.println(IsAMatch("164", "186848"));
Your logic will not work, because before i meets the length j would meet the actual length.
you dont need to have condition j < actual.length in for loop.
Your return statement should be :
return (i == expected.length() && j == actual.length()) ? true : false;
or, simpler :
return (i == expected.length() && j == actual.length());
because i and j reach the length of the strings when the loop ends.
The issue is with these two statements:
i == expected.length() - 1
j == actual.length() - 1
Remove the - 1 by each of them and it should work fine.