Search 2d Array - java

So im writing a java program which should find the shortest way from the entrance "2" to one of the numbers "3". It can only walk on " " positions. "1" is walls.
11111121
131 1
1 1 1111
1 1 13 1
1 1 11 1
1 1 1
1 1
11111111
My starting idea is to find the entrance in the 2d array. This could be done like this:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
I could also find the two "3" and save them in points. but im not sure how to return the rute to the closest "3". I was considering like a joystick, where I save the what direction you go, like (UP, DOWN, LEFT, RIGHT).
Then return the full list of moves from the entrance to the closests 3.
Got any suggestion or ideas how I could implement this ?

What you have here is simply a non-cannonical representation of a graph. You have each cell being a vertex in the graph and you have an edge between two neighboring cells if and only if both of them are free.
Now that you look at the problem in this way, find the entrance like you do and than do a breadth first search to find the exit.

I would try and create a graph with nodes and edges. Nodes are the junctions in the maze, and edges are the paths between junctions and entrance or exit objects. Each edge object has a 'weight'. Once you calculate the network from the double array, you can use some easy algorithm to work out the shortest route.

You need to make a counter that will increment every time the current position is " " (walk-able)
Notation " " = 0 in the matrix:
Point entrance = new Point(0,0);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++){
if(map[i][j] == 2){
entrance.x =i;
entrance.y =j;
}
}
Point firstexit = new Point(0,0);
int steps = 0;
int i = entrance.x;
int j = entrance.y;
int lasti = 0;
int lastj = 0;
while(true){
if(map[i][j] == 3){
firstexit.x =i;
firstexit.y =j;
break ;
}
if(map[i][j] == 0){
steps++;
}
// TO-DO : check if position exists
if(map[i][j+1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j++;
}else if(map[i][j-1] == 0 && (lasti != i && lastj != j)){
lastj = j;
j--;
}else if(map[i+1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i++;
}else if(map[i-1][j] == 0 && (lasti != i && lastj != j)){
lasti = i;
i--;
}
}

Related

Find the max sum path from bottom left side to top right cell

I have to find the maximum sum path in a 2d Array(n,m) given which has a value from 0 to 99999. 0 means wall. We have t start from the left bottom side of the array and must reach the right top cell(0,m-1). You can go up/down/right and can visit each cell once. Below is the code without any blocks .My problem is that i cant move from left bottom to right top cell . I also created left array(lest side of the main array) so that i can start from the best value possible .Sorry am not good programmer :).
Code
public static int maxvalue(int [][]field,int[] left)
{
for(int i=field.length-1;i>0 && left[i]!=-1;i--)
{
System.out.println( "Startpos "+i+" 0");
int distance =max(i,0,field,0,field.length-1);
if(distance>maxvalue)
maxvalue=distance;
}
return maxvalue;
}
public static int max(int r, int c,int [][]field ,int destR, int destC)
{
if(r>destR|| c>destC)
return 0;
if(r==0 && c==field[0].length)
return field[r][c];
int sum1=max(r-1,c,field,destR,destC); // up
System.out.println(sum1);
int sum2= max(r+1,c,field,destR,destC); //down
int sum3= max(r,c+1,field,destR,destC); //right
return field[r][c]+Math.max(sum1, Math.max(sum2, sum3));
}
Sample
Input
0 1 2 3
2 0 2 4
3 3 0 3
4 2 1 2
Output
25
How to do solve this question? if all the path is blocked then print No Solution.
Have you first tried to solve it by yourself?
It looks like a bit of work but it is not impossible.
What I would use is 3 int variables : xPosition, yPosition and Sum;
Go on and test the values of xPosition+1, yPosition-1 in priority and then the rest (because you want to reach xPosition == array.length - 1 && yPosition == 0.) and if you find a 0, test the other possibilities and exclude the ones you already passed by.
Each time you find a good path, add the value of the cell to your sum.
Reset it to 0 once you're blocked.
For every element in the array, you have to find the maximum of the adjacent elements and also check the boundary conditions. I hope this code will help you.
public class StackOverFlow {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int m = in.nextInt();
Integer [][] array = new Integer[n][m];
boolean [][] visited = new boolean[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
array[i][j] = in.nextInt();
}
}
int i = n-1, j =0;
visited[i][j] = true;
int sum = array[i][j];
while(true)
{
int max = -1;
int maxi = 0, maxj = 0;
if(i-1 >= 0 && i-1<= n-1 && j>=0 && j<= m-1 && array[i-1][j] != null && array[i-1][j]>max && !visited[i-1][j])
{
max = array[i-1][j];
maxi = i-1;
maxj=j;
}
if(i+1 >= 0 && i+1<= n-1 && j>=0 && j<= m-1 &&array[i+1][j] != null && array[i+1][j]>max && !visited[i+1][j])
{
max = array[i+1][j];
maxi = i+1;
maxj=j;
}
if(i >= 0 && i<= n-1 && j-1>=0 && j-1<= m-1 && array[i][j-1] != null && array[i][j-1]>max && !visited[i][j-1])
{
max = array[i][j-1];
maxi = i;
maxj=j-1;
}
if(i >= 0 && i<= n-1 && j+1>=0 && j+1<= m-1 && array[i][j+1] != null && array[i][j+1]>max && !visited[i][j+1])
{
max = array[i][j+1];
maxi = i;
maxj=j+1;
}
i = maxi;
j = maxj;
visited[i][j] = true;
sum += max;
if(i == 0 && j == m-1)
break;
}
System.out.println(sum);
}
}

Calculation of a total number of "0" positions between "1" positions in a vector int[]

There is a vector of 1 and 0:
int[] vec = new int[6]{0,1,0,0,1,0};
I need to calculate total number of "0" positions between "1" positions. For instance, if <0,1,0,0,1,0> then the answer is 2. However, the problem is that the vector may contain the following values:
int[] vec = new int[6]{0,1,0,0,0,0}; // the answer is 0
or
int[] vec = new int[6]{1,0,0,1,0,1}; / the answer is 3
So far, I just made a simple algorithm for the 1st case (<0,1,0,0,1,0>).
int start = 0, end = 0;
for (int i=0; i<vec.length; i++)
{
if (vec[i] == 1 && start == 0)
start = i;
if (vec[i] == 1 && start != 0)
end = i;
}
int result = end - start - 1;
I need some help with the development of more generic algorithm that could handle all the above-mentioned cases.
You can iterate over the array from both ends to find the first and last 1. Then, if you found both, count the 0s between them.
int start = -1;
int end = vec.length;
int i = 0;
int j = vec.length-1;
while (i < j) {
if (vec[i] == 1 && start < 0)
start = i;
i++;
if (vec[j] == 1 && end >= vec.length)
end = j;
j--;
if (start >= 0 && end < vec.length)
break;
}
int count = 0;
if (start >= 0 && end < vec.length) {
for (i = start + 1; i < end; i++) {
if (vec[i] == 0)
count++;
}
}
It can probably be optimized into a single loop.
Sorry, initially I thought you wanted to count the number of segments rather than the actual number of zeroes.
You can count all the zeroes after the first one (n), keeping track of the number of zeroes since the last one seen (m). Then when you reach the end of the vector, your count of n is m zeroes too high.
int count = 0;
int zeroesSinceLastOne = 0;
bool firstOneSeen = false;
for(int i = 0, n = vector.size(); i < n; ++i)
{
while(!firstOneSeen && vector[i] == 0)
{
continue;
}
firstOneSeen = true;
if(vector[i] == 0)
{
++count;
++zeroesSinceLastOne;
}
else
{
zeroesSinceLast = 0;
}
}
return count - zeroesSinceLastOnce;
Disclaimer: untested. May give the wrong number or kill your cat.
Try this algo:
startIndex = -1;
endIndex = -1;
for i from 1 to vec.length():
if( 1 == vec[i])
startIndex = i
break;
for i from vec.length() to 1:
if( 1 == vec[i])
endIndex = i
break;
ans = endIndex - startIndex - no_of_ones_in_between

dynamic programming, two player matrix game

I am programming a matrix game which is played by two player. The objective is to say whether player 1 can win the game return 1, if not return 0.
player can delete either the last row or the last column of the matrix, but only if the sum of the numbers in that row/column is even. example:
original matrix:
[1 2]
[2 2]
then we can subtract these matrices from this:
sum row, and this becomes:
[1 3] [0 0]
[2 4] [1 1]
sum col, and this becomes:
[1 2] [0 1]
[3 4] [0 1]
now we can play the game, and its clear that player 1 can remove from either the row or the column matrix. then player two can make a move, and finally we can see that player 1 cant win in this example.
here is my implementation for this program:
I only provide the method that is suppose to use the row and the column matrices and should return a 1 if player 1 wins and a 0 if player 1 ant win.
public static int play(int[][] rowM, int[][] colM){
int player = 1;
int[][] matrix = new int[rowM.length][colM[0].length];
for (int i = 0; i < rowM.length; i++) {
for (int j = 0; j < colM[0].length; j++) {
//if no possible move
if(rowM[i][j] == 0 && colM[i][j] == 0){
//if player 1 is playing, and losing
if(player % 2 == 1){
matrix[i][j] = 0;
player++;
}
//player 2 is losing
else{
matrix[i][j] = 1;
player++;
}
continue;
}
//if player 1 is playing
if(player % 2 == 1){
player++;
//the value in this position is even
if(rowM[i][j] == 1){
//if there is only 1 row left,
if(i == 0){
matrix[i][j] = 1;
}
else if(matrix[i-1][j] == 1){
matrix[i][j] = 1;
}
else{
matrix[i][j] = 0;
}
}
//the value in the col matrix this position is even
else if(colM[i][j] == 1){
//if there is only 1 column left,
if(j == 0){
//matrix[i][j] = 1;
matrix[i][j] = 1;
//player++;
}
else if (matrix[i][j-1] == 1){
matrix[i][j] = 1;
}
else{
matrix[i][j] = 0;
}
}
}
//player 2 is playing
else{
player++;
//the value in this position is even
if(rowM[i][j] == 1){
if(i == 0){
matrix[i][j] = 1;
}
else if(matrix[i-1][j] == 1){
matrix[i][j] = 0;
}
else{
matrix[i][j] = 1;
}
}
//the value in the col matrix this position is even
else if(colM[i][j] == 1){
if(j == 0){
matrix[i][j] = 1;
}
else if(matrix[i][j-1] == 1){
matrix[i][j] = 0;
}
else{
matrix[i][j] = 1;
}
}
}
}
}
return matrix[rowM.length-1][colM[0].length-1];
}
rowM and colM are matrices which have 1's and 0's inside, them, I didnt put my method that makes those matrices. this algorithm works with almost everything but I have found few examples that wont work with my implementation. I think some where in my code, specially one of the if statements must not be correct. I use debug to find it but I couldnt find out why it goes wrong.
here is an example that wot work with my code:
a matrix 2*1:
[2]
[1]
this gives me a 1, but its wrong it should be 0. Can some one help me to find my problem. this is my last option to see what am doing wrong. Please help

How to increment neighbor cells from a point in a 2D array

I am trying to make my implementation of Lee's Algorithm more efficient, so far I am using a cubed loop to increment neighboring cells in my 2D integer array:
for(int k = 1; k < g.length*2; ++k){
for(int i = x0-k; i < x1+k; ++i)
for(int j = y0-k; j < x1+k; ++j)
{
if(i > 0 && j > 0 && i < g.length-1 && j < g.length-1)
{
if(g[x1][y1] != 0)
return true;
if(g[i][j] == k && g[i+1][j] == 0){
g[i+1][j] = k + 1;
}
if(g[i][j] == k && g[i][j+1] == 0){
g[i][j+1] = k + 1;
}
if(g[i][j] == k && g[i-1][j] == 0){
g[i-1][j] = k + 1;
}
if(g[i][j] == k && g[i][j-1] == 0){
g[i][j-1] = k + 1;
}
}
}
}
Output of a 10x10 grid with points start(5,5) end(8,8):
00007670000
00076567000
00765456700
07654345600
76543234560
65432123456
76543234560
07654345600
00765456700
00076567000
00007670000
Is there a faster way of filling up the grid while also checking the value?
I know very little about this algorithm, but some material suggested that you choose your starting point as the point furthest from the center of the graph.
I ran your example, and code with this appended to the beginning:
if (d2 > d1) {
startRow = startRow ^ endRow;
endRow = startRow ^ endRow;
startRow = startRow ^ endRow;
startCol = startCol ^ endCol;
endCol = startCol ^ endCol;
startCol = startCol ^ endCol;
}
where d2 and d1 are the distances to the center from the end and start points, respectively.
I timed this over one million runs and received ~20% speed up.
Another option they suggested was to fan out from both the start point and the end point at the same time - but I wasn't sure what the stopping condition of that would be (since the target would begin at 1 in your code).
Whenever you are accessing your g array, g[i][j] for example, there are two under-the-hood checks for boundaries. If boundary check is failed, java.lang.IndexOutOfBoundsException is thrown.
You can reduce number of boundaries checks by half.
Instead of using 2D array g[W][H] , you can use simple 1D array g[W*H].
Then, instead of writing g[i][j], you can write g[i*W + j].

Messed up recursion code for a board game

What I have to do here is to count the number of adjacent white blocks (in 2's) on a square board which is made up of random black(0's) and white(1's) blocks. The white blocks have to be at i+1,j || i-1,j || i,j+1 || i,j-1. Technically diagonals are not counted. I have provided an example below:
[1 0 1]
[1 1 0]
[0 1 0]
Here count == 3 (0,0)(1,0) and (1,0)(1,1) and (1,1)(2,1)
Here is my code:
public int count = 0;
boolean count(int x, int y, int[][] mat)
{
if(x<0 || y<0)
return false;
if(mat[x][y] == 0)
return false;
for(int i = x; i<mat.length; i++)
{
for(int j = y; j<mat[0].length; j++)
{
if(mat[i][j] == 1)
{
mat[i][j] = 0;
if(count(i-1,j,mat))
count++;
if(count(i,j-1,mat))
count++;
if(count(i+1,j,mat))
count++;
if(count(i,j+1,mat))
count++;
}
}
}
return true;
}
Short explanation of what I am trying to do here: I am going about finding 1's on the board and when I find one I change it to a 0 and check its up,down,left,right for a 1. This goes on till I find no adjacent 1's. What is the thing I am missing here? I kind of have a feeling I am looping unnecessarily.
here's a solution without recursion
for(int i = 0; i < mat.length; i++) {
for(int j = 0; j < mat[i].length; j++) {
if(mat[i][j] == 1) {
if(i < mat.length - 1 && mat[i+1][j] == 1) {
count++;
}
if(j < mat[i].length - 1 && mat[i][j+1] == 1) {
count++;
}
}
}
I don't think recursion is the right answer as you should only being going one step deep (to find the adjacent value). Instead just loop through the elements looking to the right and down. Don't look up or left as twain mentioned so that you don't double count matches. Then is it simply:
for (i=0; i<max; i++)
for (j=0; j<max; j++)
if (array[i][j] == 1){
if (i<max-1 && array[i+1][j] == 1) count++;
if (j<max-1 && array[i][j+1] == 1) count++;
}

Categories