So at this point I have no idea why my for loop doesn't work. It's probably just an minor mistake but I cant find it so I'd appreciate your help. This is how it looks like:
int[] values = new int[array1.length];
for (int i = 0; i < array1.length; i++) {
for (int x = 0; x >= array1[i][0] && x <= array1[i][2]; x++) {
for (int y = 0; y >= array1[i][1] && y <= array1[i][3]; y++) {
values[i] += array2[x][y];
}
}
}
Numbers I'm using to test it on and some context:
Both arrays are 2D,
array1 looks like this:
(array1.length = 8) and array2 like this:
array1 holds coordinates of left-top and right-bottom corner of the area in array2 so for example 0 0 2 1 are coordinates for array2[0][0] and array2[2][1] and I'm trying to get my for loop to add all numbers in the area. So for this example it would add those four numbers:
My output is: 3 0 0 0 0 0 0 0
You should use explicit variable names not to do errors in meaning.
Moreover, start your loop at expected coordinates. So your loop can be written like this:
int[] values = new int[array1.length];
for (int i = 0; i < values.length; i++) {
int fromX = array1[i][0];
int fromY = array1[i][1];
int toX = array1[i][2];
int toY = array1[i][3];
for (int x = fromX; x <= toX; x++) {
for (int y = fromY; y <= toY; y++) {
values[i] += array2[x][y];
}
}
}
You can check the result:
System.out.println( Arrays.toString( values) );
// Output is [3, 0, 4, -2, 0, 1, -2, 3]
I think you should do this (add <= and >=) and change statring value. Also consider filling "values" with zeros since you're summing it up.
for (int x = array1[i][0]; x >= array1[i][0] && x =< array1[i][2]; x++) {
for (int y = array1[i][1]; y >= array1[i][1] && y =< array1[i][3]; y++) {
values[i] += array2[x][y];
}
}
Related
I'm trying to check the neighboring values of each element in a 2D array but am getting an IndexOutOfBoundsException when I reach the sides of the array or a corner. For example if my array is:
|2|4|2|7|8|
|8|1|0|5|6|
|0|3|1|5|2|
|1|9|7|2|0|
I know that all the neighbors of 8 are 7,5 and 6, but my if statements don't check the bounds properly. The code I have for this is:
int numOfRows = imageArray.length;
int numOfColumns = imageArray[0].length;
for(int i = 0; i < numOfRows; i++)
for(int j = 0; j < numOfColumns; j++)
if((j+1) < numOfColumns-1)
if((i+1) < numOfRows-1)
if((j-1) > 0 )
if((i-1) > 0 )
if((i+1) < numOfColumns-1 && (j+1) < numOfRows-1)
if((i-1) >= 0 && (j-1) >= 0)
if((i+1) < numOfColumns-1 && (j-1) >= 0)
if((i-1) >= 0 && (j+1) < numOfRows-1)
I've been working on this for a while and have gone through many different techniques to solve this. Any help would be great. Thanks.
If you're trying to get all the neighbor cells and do something with them, for example add them, then you need to do some sort of bounds checking, for example something modified from this could work:
for (int i = 0; i < numOfRows; i++) {
for (int j = 0; j < numOfCols; j++) {
// check all bounds out of range:
int iMin = Math.max(0, i - 1);
int iMax = Math.min(numOfRows - 1, i + 1);
int jMin = Math.max(0, j - 1);
int jMax = Math.min(numOfCols - 1, j + 1);
// loop through the above numbers safely
for (int innerI = iMin; innerI <= iMax; innerI++) {
for (int innerJ = jMin; innerJ <= jMax; innerJ++) {
if (i != innerI && j != innerJ) {
// do what needs to be done
}
}
}
}
}
Caveat: code has not been compiled nor tested and is mainly to show you the idea of what can be done rather than a copy-paste solution
I'm working on a coding question and I'm given an array for example something like this: [1, 7, 3, 21, 13, 19]
I'm suppose to pair up items in the array. Then after that I'm suppose to apply this simple rule.
Say I choose a pair x and y:
Rule:
if x > y : y = 2*y and x = x - y
if y > x : x = 2*x and y = y - x
if x == y : break # x and y is a pair that does not cause an infinite loop
Example:
Say x = 7 and y = 3
1st round : x = 7 and y = 3
2nd round : x = 4 and y = 6
3rd round : x = 8 and y = 2
4th round : x = 6 and y = 4
at this point you know that this pair will loop forever
If for example x = 1 and y = 3
1st round : x = 1 and y = 3
2nd round : x = 2 and y = 2
At this point you know that this pair doesn't loop
So in order to solve this problem. I saw it as some kind of TSP but instead of minimizing path, I'm maximizing path.
So first step I did is create a graph of nodes and label whether a pair is a loop or not
In this array the graph generated (adjacency matrix) is this:
0 0 0 1 1 1
0 0 1 0 1 1
0 1 0 0 0 1
1 0 0 0 1 1
1 1 0 1 0 0
1 1 1 1 0 0
the index in the graph represent index in the array. For example let's say that i is row and j is column. If you look at i=0, j=2 that represents array[i] = x, array[j] = y which is array[0] = x = 1, array[2] = y = 3. From the above example we know that that is not a loop. Therefore there is a 0 weight on that index.
Then I do a nearest neighbor TSP algorithm (modified to be max route) in order to get the max pair that maximized the amount of loop pairs. This method passes the coding test cases except for one. I can't identify an array of integers that would fail my code. And the test cases on the coding challenge does not give me any info on what test it is failing on.
Here is my code:
import java.util.HashMap;
public class DistractTheGuards {
private static boolean IsPairLoop(int first, int second)
{
long result = first + second;
boolean success = true;
while ((result & 1) == 0)
{
if (first == second)
{
success = false;
break;
}
else if (first > second)
{
first = (first - second) / 2;
}
else
{
second = (second - first) / 2;
}
result = first + second;
}
return success;
}
public static void GenWeights(int[][] graph, int[] banana_list)
{
for (int i = 0; i < graph.length; ++i)
{
for (int j = 0; j < graph.length; ++j)
{
if (IsPairLoop(banana_list[i], banana_list[j]))
{
graph[i][j] = 1;
}
else
{
graph[i][j] = 0;
}
}
}
}
private static boolean AreAllNodesVisited(boolean[] visited)
{
boolean all_visited = true;
for (int i = 0; i < visited.length; ++i)
{
all_visited &= visited[i];
if (!all_visited)
break;
}
return all_visited;
}
private static int FindMaxTourKey(HashMap<Integer, int[]> tours)
{
int cur_max_r = -1;
for (Integer rank : tours.keySet())
{
if (cur_max_r < rank)
cur_max_r = rank;
}
return cur_max_r;
}
private static int GetN(int[][] graph, int[] max_tour, int n)
{
for (int i = 0; i < max_tour.length; i += 2)
{
if (i + 1 >= max_tour.length)
break;
if (graph[max_tour[i]][max_tour[i+1]] == 0)
{
n -= 2;
}
}
return n;
}
public static int answer(int[] banana_list)
{
int n = banana_list.length;
if (n < 1)
return 0;
if (n == 1)
return 1;
int[][] graph = new int[n][n];
GenWeights(graph, banana_list);
HashMap<Integer, int[]> tours = new HashMap<>();
for (int i = 0; i < n; ++i)
{
int[] cur_tour = new int[n];
boolean[] visited = new boolean[n];
int start_node = i;
int cur_tour_i = 0;
while (!AreAllNodesVisited(visited))
{
int s_n = start_node;
visited[start_node] = true;
cur_tour[cur_tour_i++] = start_node;
int cur_max = 0;
for (int j = 0; j < n; ++j)
{
if (!visited[j])
{
if (cur_max < graph[start_node][j])
{
cur_max = graph[start_node][j];
start_node = j;
break;
}
}
}
if (s_n == start_node)
{
for (int x = n - 1; x >= 0; --x)
{
if (!visited[x])
{
start_node = x;
break;
}
}
}
}
int cur_tour_r = 0;
for (int x = 0; x < n; x += 2)
{
if (x + 1 >= n)
break;
cur_tour_r += graph[cur_tour[x]][cur_tour[x+1]];
}
tours.put(cur_tour_r, cur_tour.clone());
if (cur_tour_r == n - 1)
break;
}
int cur_max_r = FindMaxTourKey(tours);
if (tours.size() == 0)
return 0;
int[] max_tour = tours.get(cur_max_r);
return GetN(graph, max_tour, n);
}
}
I just need help identifying an edge case that would fail my method. Can anyone help me or give me an array that would certainly fail my method? I can take it from there. Thanks
Update
Constraints
1 <= integers <= 2^30
1 <= len(array) <= 100
I have a large array of arbitrary size. It's a square array. I'm trying to grasp how to traverse it diagonally like a / rather than a \ (what I already know how to do). I have the following code thus far:
char[][] array = new char[500][500];
//array full of random letters
String arrayLine = "";
for (int y = 0; y < array.length; y++) {
for (int x = 0; x < array.length; x++) {
for (???) {
arrayLine = arrayLine + array[???][???];
}
}
System.out.println(arrayLine);
}
I have three loops, because this is how I did the other diagonal:
for (int y = 0; y < array.length; y++) {
for (int x = 0; x < array.length; x++) {
for (int z = 0; z < array.length-y-x; z++) {
arrayLine = arrayLine + array[y+z][x+z];
}
}
System.out.println(arrayLine);
}
In my attempts, I keep going outside the boundaries and get an ElementOutOfBounds exception. Say the array is as below (a 3x3 instead of 500x500):
A B C
D E F
G H I
I want to print out the following as strings:
A
BD
CEG
FH
I
A previous SO question had a similar problem with integer arrays, and the solution is based off of the sum of array elements. But I'm working with chars, so I can't think of a methodology to get it.
Think about the coordinates of the cells:
. 0 1 2
0 A B C
1 D E F
2 G H I
For any diagonal, all of the elements have something in common: the sum of an element's coordinates is a constant. Here are the constants:
0 = 0+0 (A)
1 = 1+0 (B) = 0+1 (D)
2 = 2+0 (C) = 1+1 (E) = 0+2 (G)
3 = 2+1 (F) = 1+2 (H)
4 = 2+2 (I)
The minimum constant is the smallest coordinate sum, 0. The maximum constant is the largest coordinate sum. Since each coordinate component can go up to array.length - 1, the maximum constant is 2 * (array.length - 1).
So the thing to do is iterate over the constants. For each constant, iterate over the elements whose coordinates sum to the constant. This is probably the simplest approach:
for (int k = 0; k <= 2 * (array.length - 1); ++k) {
for (int y = 0; y < array.length; ++y) {
int x = k - y;
if (x < 0 || x >= array.length) {
// Coordinates are out of bounds; skip.
} else {
System.out.print(array[y][x]);
}
}
System.out.println();
}
However, that will end up iterating over a lot of out-of-bounds coordinates, because it always iterates over all possible y coordinates, even though only one diagonal contains all possible y coordinates. Let's change the y loop so it only visits the y coordinates needed for the current k.
One condition for out-of-bounds coordinates is x < 0. Substitute the definition of x and solve:
x < 0
k - y < 0
k < y
y > k
So when y > k, x will be negative. Thus we only want to loop while y <= k.
The other condition for out-of-bounds coordinates is x >= array.length. Solve:
x >= array.length
k - y >= array.length
k - array.length >= y
y <= k - array.length
So when y <= k - array.length, x will be too large. Thus we want to start y at 0 or k - array.length + 1, whichever is larger.
for (int k = 0; k <= 2 * (array.length - 1); ++k) {
int yMin = Math.max(0, k - array.length + 1);
int yMax = Math.min(array.length - 1, k);
for (int y = yMin; y <= yMax; ++y) {
int x = k - y;
System.out.print(array[y][x]);
}
System.out.println();
}
Note: I have only proven this code correct. I have not tested it.
Much simpler way is to check the sum if indexes are equals to the array.length = 1; for diagonalRight and for diagonalLeft just check if i is equals j
Example:
digonalLeft sums \ of matrix, because (0,0) (1,1) (2,2) makes the diagonal.
diagonalRight sums / of matrix, because (0+2) = (1+1) = (2+0) = 2 and 2 is the array.length - 1.
long diagonalLeft = 0;
long diagonalRight = 0;
for (int i = 0; i < array.lenth - 1; i++) {
for (int j = 0; j < array.length -1; j++) {
if (i == j) digonalLeft += array[i][j];
if (i + j == array.length - 1) diagonalRight += array[i][j];
}
}
You are given a 2D array as a string and a word via keyboard. The word
can be in any way (all 8 neighbors to be considered) but you can’t use
same character twice while matching. Return word's first and last
character's index as (x,y). If match is not found return -1.
That's the question. I'm having trouble with searching. I tried that:
int x=0,y=0;
for(int f=0; f<WordinArray.length; f++){
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(matrix[i][j].equals(WordinArray[f])){
x=i; y=j;
System.out.print("("+x+","+y+")");
}
}
}
}
But, That code is not working as it is supposed to. How else I can write this searching code?
Referring to Sixie's code
Assuming this is a valid input/output to your program?
Size:
4x4
Matrix:
a b c d
e f g h
i j k l
m n o p
Word: afkp
(0,0)(3,3)
I edited your code, so that it should work for input on this form (it is case sensitive at the moment, but can easily be changed by setting .toLowerCase()
Scanner k = new Scanner(System.in);
System.out.println("Size: ");
String s = k.nextLine();
s.toUpperCase();
int Xindex = s.indexOf('x');
int x = Integer.parseInt(s.substring(0, Xindex));
int y = Integer.parseInt(s.substring(Xindex + 1));
System.out.println("Matrix:");
char[][] matrix = new char[x][y];
for (int i = 0; i < x; i++) {
for (int p = 0; p < y; p++) {
matrix[i][p] = k.next().charAt(0);
}
}
System.out.print("Word: ");
String word = k.next();
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
// looping through the matrix
for (int i = 0; i < x; i++) {
for (int j = 0; j < y; j++) {
// when a match is found at the first character of the word
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
// calculating all the 8 normals in the x and y direction
// (the 8 different directions from each cell)
for (int normalX = -1; normalX <= 1; normalX++) {
for (int normalY = -1; normalY <= 1; normalY++) {
// go in the given direction for the whole length of
// the word
for (int wordPosition = 0; wordPosition < word
.length(); wordPosition++) {
// calculate the new (x,y)-position in the
// matrix
int xPosition = i + normalX * wordPosition;
int yPosition = j + normalY * wordPosition;
// if the (x,y)-pos is inside the matrix and the
// (x,y)-vector normal is not (0,0) since we
// dont want to check the same cell over again
if (xPosition >= 0 && xPosition < x
&& yPosition >= 0 && yPosition < y
&& (normalX != 0 || normalY != 0)) {
// if the character in the word is not equal
// to the (x,y)-cell break out of the loop
if (matrix[xPosition][yPosition] != word
.charAt(wordPosition))
break;
// if the last character in the word is
// equivalent to the (x,y)-cell we have
// found a full word-match.
else if (matrix[xPosition][yPosition] == word
.charAt(wordPosition)
&& wordPosition == word.length() - 1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xPosition;
yEnd = yPosition;
}
} else
break;
}
}
}
}
}
}
System.out.println("(" + xStart + "," + yStart + ")(" + xEnd + ","
+ yEnd + ")");
k.close();
I think you need to plan your algorithm a bit more carefully before you start writing code. If I were doing it, my algorithm might look something like this.
(1) Iterate through the array, looking for the first character of the word.
(2) Each time I find the first character, check out all 8 neighbours, to see if any is the second character.
(3) Each time I find the second character as a neighbour of the first, iterate along the characters in the array, moving in the correct direction, and checking each character against the word.
(4) If I have matched the entire word, then print out the place where I found the match and stop.
(5) If I have reached the edge of the grid, or found a character that doesn't match, then continue with the next iteration of loop (2).
Once you have your algorithm nailed down, think about how to convert each step to code.
If I understood your question right. This is a quick answer I made now.
int H = matrix.length;
int W = matrix[0].length;
int xStart = -1, yStart = -1;
int xEnd = -1, yEnd = -1;
String word = "WordLookingFor".toLowerCase();
for (int i = 0; i < H; i++) {
for (int j = 0; j < W; j++) {
if (matrix[i][j] == word.charAt(0)) {
int tempxStart = i;
int tempyStart = j;
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
for (int k = 0; k < word.length(); k++) {
int xx = i+x*k;
int yy = j+y*k;
if(xx >= 0 && xx < H && yy >= 0 && yy < W && (x != 0 || y != 0)) {
if(matrix[xx][yy] != word.charAt(k))
break;
else if (matrix[xx][yy] == word.charAt(k) && k == word.length()-1) {
xStart = tempxStart;
yStart = tempyStart;
xEnd = xx;
yEnd = yy;
}
} else
break;
}
}
}
}
}
}
A little trick I used for checking all the 8 neighbors is to use two for-loops to create all the directions to go in:
for (int x = -1; x <= 1; x++) {
for (int y = -1; y <= 1; y++) {
if(x !=0 || y != 0)
System.out.println(x + ", " + y);
}
}
This creates
-1, -1
-1, 0
-1, 1
0, -1
0, 1
1, -1
1, 0
1, 1
Notice: All but 0,0 (you don't want to revisit the same cell).
The rest of the code is simply traversing though the matrix of characters, and though the whole length of the word you are looking for until you find (or maybe you don't find) a full match.
This time the problem is that how could I print word's first and last
letter's indexes. I tried various ways like printing after each word
was searched. But, all of them didn't work. I am about to blow up.
int[] values = new int[2];
for(int i=0; i<matrix.length; i++){
for(int j=0; j<matrix[0].length; j++){
if(Character.toString(word.charAt(0)).equals(matrix[i][j]) == true || Character.toString(ReversedWord.charAt(0)).equals(matrix[i][j]) == true ){
System.out.print("("+ i + "," +j+")");
//First letter is found.Continue.
for(int p=1; p<word.length(); p++){
try{
for (int S = -1; S <= 1; S++) {
for (int SS = -1; SS <= 1; SS++) {
if(S !=0 || SS != 0)
if(matrix[i+S][j+SS].equals(Character.toString(word.charAt(p))) && blocksAvailable[i+S][j+SS] == true ||
matrix[i+S][j+SS].equals(Character.toString(ReversedWord.charAt(p))) && blocksAvailable[i+S][j+SS] == true) {
values[0] = i+S;
values[1] = j+SS;
blocksAvailable[i+S][j+SS] = false;
}
}
}
}catch (ArrayIndexOutOfBoundsException e) {}
I set up a two dimensional array, 10 by 10, and each slot is (x*y) for its respective position. I'm trying to add up all numbers in columns 3, 5, and 7 into cTotal and add up all numbers in rows 2, 4, and 6 into rTotal. My coding seems sound but I just can't seem to make it work. Any ideas?
public static void arrayMath()
{
int cTotal = 0;
int rTotal = 0;
//int tDiffValue = (rTotal - cTotal);
int twodimarr[][] = new int[10][10];
int row = 10;
int col = 10;
int x = 0;
int y = 0;
for(x = 0; x < row; x++)
{
for(y = 0; y < col; y++)
{
twodimarr[x][y] = x*y;
}
}
for(x = 0; x < row; x++)
{
for(y = 0; y < col; y++)
{
if( (x+y) < col )
{
//System.out.print( " " );
}
//System.out.print(" " + (twodimarr[x][y]));
}
//System.out.println();
}
for(x = 0; x < twodimarr.length; x++) //Problems start down here.
{
for( y= 0; y<twodimarr.length; y++)
{
if(y == 2 || y == 4 || y == 6)
{
rTotal = ((rTotal + twodimarr[x][y]));
}
}
}
System.out.println("rTotal is " + rTotal + ".");
for(x = 0; x < twodimarr.length; x++)
{
for(y = 0; y < twodimarr.length; y++)
{
if(x == 3 || x == 5 || x == 7)
{
cTotal = ((cTotal + twodimarr[x][y]));
}
}
}
System.out.print("cTotal is " + cTotal + ".");
}
x==3 isn't the third column, it's the 4th(0,1,2,3). That meaning it's the column of 3*0, 3*1, etc. and the 675/540 numbers are correct in that case.
Array indexes start at 0. To get the rows/columns you want you need to subtract 1 from the numbers you are checking. For rows 2, 4, 6 check if y == 1, 3, 5. For columns 3, 5, 7 check if x == 2, 4, 6.