More efficient way to check neighbours in a two-dimensional array in Java - java

Hey all, for a few of my college assignments I've found the need to check neighbouring cells in 2-dimensional arrays (grids). The solution I've used is a bit of a hack using exceptions, and I'm looking for a way to clean it up without having loads of if statements like some of my classmates. My current solution is
for ( int row = 0; row < grid.length; row++ ) {
for ( int col = 0; col < grid.length; col++ ) {
// this section will usually be in a function
// checks neighbours of the current "cell"
try {
for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
for ( int colMod = -1; colMod <= 1; colMod++ ) {
if ( someVar == grid[row+rowMod][col+colMod] ) {
// do something
}
}
}
} catch ( ArrayIndexOutOfBoundsException e ) {
// do nothing, continue
}
// end checking neighbours
}
}
I shudder to think of the inefficiency using exceptions to get my code to work causes, so I'm looking for suggestions as to how I could remove the reliance on exceptions from my code without sacrificing readability if it's possible, and just how I could make this code segment generally more efficient. Thanks in advance.

You can try this.
First decide the size of the grid Lets say its 8 X 8 & assign MIN_X = 0, MIN_Y = 0, MAX_X =7, MAX_Y =7
Your curren position is represented by thisPosX , thisPosY, then try this:
int startPosX = (thisPosX - 1 < MIN_X) ? thisPosX : thisPosX-1;
int startPosY = (thisPosY - 1 < MIN_Y) ? thisPosY : thisPosY-1;
int endPosX = (thisPosX + 1 > MAX_X) ? thisPosX : thisPosX+1;
int endPosY = (thisPosY + 1 > MAX_Y) ? thisPosY : thisPosY+1;
// See how many are alive
for (int rowNum=startPosX; rowNum<=endPosX; rowNum++) {
for (int colNum=startPosY; colNum<=endPosY; colNum++) {
// All the neighbors will be grid[rowNum][colNum]
}
}
you can finish it in 2 loops.

So row and col currently contain the coordinate of the cell that I want to check the neighbours of. So if I have a class variable called START_OF_GRID which contains 0, my solution would be as follows:
int rowStart = Math.max( row - 1, START_OF_GRID );
int rowFinish = Math.min( row + 1, grid.length - 1 );
int colStart = Math.max( col - 1, START_OF_GRID );
int colFinish = Math.min( col + 1, grid.length - 1 );
for ( int curRow = rowStart; curRow <= rowFinish; curRow++ ) {
for ( int curCol = colStart; curCol <= colFinish; curCol++ ) {
// do something
}
}

why can't you check row+rowMod and col+colMod for validity before array access?
something like:
r=row+rowMod;
c=col+colMod;
if (r < 0 || c < 0 || r >= grid.length || c >= grid.length) continue;
alternatively (no continue):
if (r >= 0 && c >= 0 && r < grid.length && c < grid.length &&
someVar == grid[r][c]) { /* do something */ }

The basic principle is not to access things that are out of bounds -- so either protect the bounds or don't go out of bounds in the first place. That is, start at a place where you won't immediately go out of bounds and stop before you get out of bounds.
for ( int row = 1; row < grid.length - 1; row++ ) {
for ( int col = 1; col < grid.length - 1; col++ ) {
// this section will usually be in a function
// checks neighbours of the current "cell"
for ( int rowMod = -1; rowMod <= 1; rowMod++ ) {
for ( int colMod = -1; colMod <= 1; colMod++ ) {
if ( someVar == grid[row+rowMod][col+colMod] ) {
// do something
}
}
}
// end checking neighbours
}
}
Like your current code, this doesn't necessarily deal appropriately with edge conditions -- that is, it applies a 3x3 grid everywhere that the 3x3 grid fits within the matrix, but does not shrink the grid to a 2x2, 2x3 or 3x2 grid when on the edge of the matrix. It will, however, allow a method in the main body checking a 3x3 grid to observe every cell in the matrix.

If I understand your code correctly, and am correctly guessing your concerns, you're trying to avoid checking a non-existent neighbour when the cell of interest is on one edge of the grid. One approach, which may or may not suit your application, is to put a 1-cell wide border all the way round your grid. You then run your loops across the interior of this expanded grid, and all the cells you check have 4 neighbours (or 8 if you count the diagonally neighbouring cells).

How about this:
private static void printNeighbours(int row, int col, int[][] Data, int rowLen, int colLen)
{
for(int nextR=row-1; nextR<=row+1; nextR++)
{
if(nextR<0 || nextR>=rowLen)
continue; //row out of bound
for(int nextC=col-1; nextC<=col+1; nextC++)
{
if(nextC<0 || nextC>=colLen)
continue; //col out of bound
if(nextR==row && nextC==col)
continue; //current cell
System.out.println(Data[nextR][nextC]);
}
}
}

private void fun(char[][] mat, int i, int j){
int[] ith = { 0, 1, 1, -1, 0, -1 ,-1, 1};
int[] jth = { 1, 0, 1, 0, -1, -1 ,1,-1};
// All neighbours of cell
for (int k = 0; k < 8; k++) {
if (isValid(i + ith[k], j + jth[k], mat.length)) {
//do something here
}
}
}
private boolean isValid(int i, int j, int l) {
if (i < 0 || j < 0 || i >= l || j >= l)
return false;
return true;
}

Related

Java: How to move a knight on a chessboard until no possible moves are left

I have an assignment to have a knight move around the chessboard until it either completes a full tour or has no where else to go.
im having a problem figuring out how to have it actually stop after there are no more moves. I have the algorithm for the movement down, as well as bounds checking on the chessboard.
setting the loop count to 64 just times out, because the program will try to continually find a spot that doesn't exist if a perfect tour isn't created.
two ideas I have had to fix this is to either increment a variable every time a certain position is checked around a certain spot, and if all possible moves are taken by a previous move, terminate the program. Problem is I have no idea how to actually do this.
A second idea I had is to have the program quit the for loop after 2 seconds(during which the for loop will check each position way more than once) but I feel like my professor would crucify me upside down if I did that
here is my code:
import apcslib.*; //this is only for Format()
public class ktour
{
int[][] kboard = new int[9][9];
int[] vert = new int[9];
int[] horiz = new int[9];
ktour()
{
vert[1] = -2;vert[2] = -1;vert[3] = 1;vert[4] = 2;vert[5] = 2;vert[6] = 1;vert[7] = -1;vert[8] = -2;
horiz[1] = 1;horiz[2] = 2;horiz[3] = 2;horiz[4] = 1;horiz[5] = -1;horiz[6] = -2;horiz[7] = -2;horiz[8] = -1;
path();
}
public void path()
{
int row = 1;
int col = 1;
int loops = 10; //i have this set to 10 for now
int col2 = 1;
int row2 = 1;
int r = (int)(Math.random() * (8) +1); //returns a random from 1 to 9
//System.out.println(r);
kboard[col][row] = 1;
for(int x = 2; x < loops; x++) //this runs the bounds check and places each number for the amount that loops is
{
r = (int)(Math.random() * (8) +1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
while(col <= 0 || col > 8 || row <= 0 || row > 8) //bounds check, will keep running until both row and columb is in the board
{
r = (int)(Math.random() * (8) + 1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
}
if(kboard[col][row] == 0)
{
kboard[col][row] = x;
row2 = row;
col2 = col;
}
else
{
x--; //if the above if is false and a number already occupies the generated spot, x is decremented and the program tries again
}
}
printboard();
}
public void printboard()
{
for(int y = 1; y < 9; y++)
{
System.out.println();
for(int x = 1; x < 9; x++)
{
System.out.print(Format.right(kboard[y][x],3));
}
}
}
}
I was able to fix my lab with the following code. I created a variable called count which I used to check if at any move there were no more moves left. As there are only 8 moves, when the variable reached 9 the code terminated, and printed up to the point it got to.
I had to put multiple if statements excluding r = math.random if count was not 0, meaning I was checking r 1-9, aka every possible move. Therefore, I couldn't use a randomizer, I had to traverse all 8 possible moves.
I also ran into problems when I reached the line where it checks if kboard[col][row] == 0. if you were running through a loop with count greater than 1, it was possible that col or row could be out of bounds, due to lack of a randomizer in the bounds checker. If left without a break, the bounds checker would run forever without a random number generated every time. I fixed this by adding an if statement that allowed the program to proceed if col and row were inside the board. if they were not, x was decremented and count was increased again, signifying a failed attempt.
This way I was able to check all possible moves, disregarding whether or not they were inside the board.
public void path()
{
int row = 1;
int col = 1;
int loops = 64; //i have this set to 10 for now
int col2 = 1;
int row2 = 1;
int count = 0;
boolean end = false;
int r = (int)(Math.random() * (8) +1); //returns a random from 1 to 9
//System.out.println(r);
kboard[col][row] = 1;
for(int x = 2; x < loops; x++) //this runs the bounds check and places each number for the amount that loops is
{
if(count == 0)
r = (int)(Math.random() * (8) +1);
if(count >= 1 && r != 8)
r++;
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
while(col <= 0 || col > 8 || row <= 0 || row > 8) //bounds check, will keep running until both row and columb is in the board
{
if(count == 0)
r = (int)(Math.random() * (8) + 1);
col = col2;
row = row2;
col = col + vert[r];
row = row + horiz[r];
if(count >= 1)
break;
}
end = false;
if(r == 8 || r == 9)
r = 1;
if(count >= 9)
{
System.out.println("Halting... no where else to go");
loops = 0;
}
if(!(col <= 0 || row <= 0 || row > 8 || col > 8))
{
if(kboard[col][row] == 0)
{
kboard[col][row] = x;
row2 = row;
col2 = col;
count = 0;
}
else
{
count++;
x--; //if the above if is false and a number already occupies the generated spot, x is decremented and the program tries again
}
}
else
{
count++;
x--;
}
}
printboard();
}

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);
}
}

How to print out an X using nested loops

I have searched through to find a simple solution to this problem.
I have a method called
printCross(int size,char display)
It accepts a size and prints an X with the char variable it receives of height and width of size.
The calling method printShape(int maxSize, char display) accepts the maximum size of the shape and goes in a loop, sending multiples of 2 to the printCross method until it gets to the maximum.
Here is my code but it is not giving me the desired outcome.
public static void drawShape(char display, int maxSize)
{
int currentSize = 2; //start at 2 and increase in multiples of 2 till maxSize
while(currentSize<=maxSize)
{
printCross(currentSize,display);
currentSize = currentSize + 2;//increment by multiples of 2
}
}
public static void printCross(int size, char display)
{
for (int row = 0; row<size; row++)
{
for (int col=0; col<size; col++)
{
if (row == col)
System.out.print(display);
if (row == 1 && col == 5)
System.out.print(display);
if (row == 2 && col == 4)
System.out.print(display);
if ( row == 4 && col == 2)
System.out.print(display);
if (row == 5 && col == 1)
System.out.print(display);
else
System.out.print(" ");
}
System.out.println();
}
}
Is it because I hardcoded the figures into the loop? I did a lot of math but unfortunately it's only this way that I have been slightly close to achieving my desired output.
If the printCross() method received a size of 5 for instance, the output should be like this:
x x
x x
x
x x
x x
Please I have spent weeks on this and seem to be going nowhere. Thanks
The first thing you have to do is to find relationships between indices. Let's say you have the square matrix of length size (size = 5 in the example):
0 1 2 3 4
0 x x
1 x x
2 x
3 x x
4 x x
What you can notice is that in the diagonal from (0,0) to (4,4), indices are the same (in the code this means row == col).
Also, you can notice that in the diagonal from (0,4) to (4,0) indices always sum up to 4, which is size - 1 (in the code this is row + col == size - 1).
So in the code, you will loop through rows and then through columns (nested loop). On each iteration you have to check if the conditions mentioned above are met. The logical OR (||) operator is used to avoid using two if statements.
Code:
public static void printCross(int size, char display)
{
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
if (row == col || row + col == size - 1) {
System.out.print(display);
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
Output: (size = 5, display = 'x')
x x
x x
x
x x
x x
Instead of giving a direct answer, I will give you some hints.
First, you are right to use nested for loops.
However as you noticed, you determine when to print 'x' for the case of 5.
Check that 'x' is printed if and only if row = col or row + col = size - 1
for your printCross method, try this:
public static void printCross(int size, char display) {
if( size <= 0 ) {
return;
}
for( int row = 0; row < size; row++ ) {
for( int col = 0; col < size; col++ ) {
if( col == row || col == size - row - 1) {
System.out.print(display);
}
else {
System.out.print(" ");
}
}
System.out.println();
}
}
ah, I got beaten to it xD
Here's a short, ugly solution which doesn't use any whitespace strings or nested looping.
public static void printCross(int size, char display) {
for (int i = 1, j = size; i <= size && j > 0; i++, j--) {
System.out.printf(
i < j ? "%" + i + "s" + "%" + (j - i) + "s%n"
: i > j ? "%" + j + "s" + "%" + (i - j) + "s%n"
: "%" + i + "s%n", //intersection
display, display
);
}
}
Lte's try this simple code to print cross pattern.
class CrossPattern {
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
System.out.println("enter the number of rows=column");
int n = s.nextInt();
int i, j;
s.close();
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
if (j == i) {
System.out.print("*");
} else if (j == n - (i - 1)) {
System.out.print("*");
} else {
System.out.print(" ");
}
}
System.out.println();
}
}
}

Checking a grid, throwing out of bounds exceptions

Currently, I'm trying to check a grid cells for data in all cells around it. Up, left, down, right, and all diagonals. How can I use exception throwing so I don't have to individually code the sides and corners?
This is currently what I have. isIsAlive() simply checks to see if the cell is "active". Neighbors for a cell include all active cells around it.
public void calcNeighbors() throws ArrayIndexOutOfBoundsException{
int x =0;
int y =0;
int neighbors = 0;
while(x < 9){
while(y < 9){
if(generation[x+1][y+1].isIsAlive()){
neighbors++;
}
if(generation[x+1][y].isIsAlive()){
neighbors++;
}
if(generation[x+1][y-1].isIsAlive()){
neighbors++;
}
if(generation[x][y-1].isIsAlive()){
neighbors++;
}
if(generation[x-1][y-1].isIsAlive()){
neighbors++;
}
if(generation[x-1][y].isIsAlive()){
neighbors++;
}
if(generation[x-1][y+1].isIsAlive()){
neighbors++;
}
if(generation[x][y+1].isIsAlive()){
neighbors++;
}
y++;
}
x++;
neighbors = 0;
}
}
Your list of if blocks is ugly (to be blunt) and dangerous. Instead use nested for loops but calculate the upper and lower bounds of the for loops taking the edges into consideration.
for (int x = 0; x < MAX_X; x++) {
for (int y = 0; y < MAX_Y; y++) {
int minRow = Math.max(0, x - 1);
int maxRow = Math.min(MAX_X - 1, x + 1);
int minCol = Math.max(0, y - 1);
int maxCol = Math.min(MAX_Y - 1, y + 1);
for (int row = minRow; row <= maxRow; row++) {
for (int col = minCol; col <= maxCol; col++) {
if (row != x || col != y) {
if(generation[row][col].isIsAlive()){
neighbors[x, y]++;
}
}
}
}
}
}
You shouldn't throw your own exception if the hypothetical neighbor would be out of bounds. Java would throw an ArrayIndexOutOfBoundsException anyway.
You need to check your bounds before you access the array; don't access the array if either your x or y is out of range.
It's not recommended to use exceptions for this purpose. But if you insist, you could do it in the following way. First, define a method
public boolean isAlive(int x,int y) {
try {
return this.generation[x][y].isIsAlive() ;
} catch(IndexOutOfBoundsException ex) {
return false ; // Or whatever you want to be the default
}
}
And then use isAlive(x+1,y+1) instead of generation[x+1][y+1].isIsAlive() and so on.
Additionally, my impression is that you are mistakenly declaring a local variable int neighbors = 0;. I say this because you keep setting it to 0 at the end, but you don't store it anywhere. Personally, I would define a field neighbors in whatever is the base class of generation and:
for(int x= 0 ; x < generation.length ; x++ ) {
for(int y= 0 ; y < generation[x].length ; y++ ) {
generation[x][y].neighbors= 0 ;
for(int dx= -1 ; dx <= 1 ; dx++ ) {
for(int dy= -1 ; dy <= 1 ; dy++ ) {
if( ! ( dx == 0 && dy == 0 ) && isAlive(x+dx,y+dx) ) {
generation[x][y].neighbors++;
}
}
}
}
My concern with so many ifs are 3:
1. It's very easy to make a mistake.
2. It will be time consuming (and error-prone) to add any other code inside all ifs.
3. The logic is easier to understand. Though you could also add a comment explaining that you are going to check neighbors, and that neighbors are all 8 cells where row or column is +1 or -1 the current cell.
Also, now that we have reduced the number of ifs, we could also inline the function above and write the following:
for(int x= 0 ; x < generation.length ; x++ ) {
for(int y= 0 ; y < generation[x].length ; y++ ) {
generation[x][y].neighbors= 0 ;
for(int dx= -1 ; dx <= 1 ; dx++ ) {
for(int dy= -1 ; dy <= 1 ; dy++ ) {
try {
if( ! ( dx == 0 && dy == 0 ) && isAlive(x+dx,y+dx) ) {
generation[x][y].neighbors++;
}
} catch(IndexOutOfBoundsException ex) {
// Do whatever you want in this case
}
}
}
}
}
Now, without abusing exceptions (which is by far the most recommended), I'd say add a function
public boolean isValidNeighbor(int i,int j) {
return 0 <= i && i < generation.length && 0 <= j && j < generation[i].length ;
}
And your code becomes:
for(int x= 0 ; x < generation.length ; x++ ) {
for(int y= 0 ; y < generation[x].length ; y++ ) {
generation[x][y].neighbors= 0 ;
for(int dx= -1 ; dx <= 1 ; dx++ ) {
for(int dy= -1 ; dy <= 1 ; dy++ ) {
if( ! ( dx == 0 && dy == 0 ) && isValidNeighbor(x+dx,y+dx) && isAlive(x+dx,y+dx) ) {
generation[x][y].neighbors++;
}
}
}
}
}
Much, much better. And, even if not the main reason, less code and complexity than with exceptions!!!

Algorithm for finding all paths in a NxN grid

Imagine a robot sitting on the upper left hand corner of an NxN grid. The robot can only move in two directions: right and down. How many possible paths are there for the robot?
I could find solution to this problem on Google, but I am not very clear with the explanations. I am trying to clearly understand the logic on how to solve this and implement in Java. Any help is appreciated.
Update: This is an interview question. For now, I am trying to reach the bottom-right end and print the possible paths.
public static int computePaths(int n){
return recursive(n, 1, 1);
}
public static int recursive(int n, int i, int j){
if( i == n || j == n){
//reach either border, only one path
return 1;
}
return recursive(n, i + 1, j) + recursive(n, i, j + 1);
}
To find all possible paths:
still using a recursive method. A path variable is assigned "" in the beginning, then add each point visited to 'path'. A possible path is formed when reaching the (n,n) point, then add it to the list.
Each path is denoted as a string, such as " (1,1) (2,1) (3,1) (4,1) (4,2) (4,3) (4,4)". All possible paths are stored in a string list.
public static List<String> robotPaths(int n){
List<String> pathList = new ArrayList<String>();
getPaths(n, 1,1, "", pathList);
return pathList;
}
public static void getPaths(int n, int i, int j, String path, List<String> pathList){
path += String.format(" (%d,%d)", i , j);
if( i ==n && j == n){ //reach the (n,n) point
pathList.add(path);
}else if( i > n || j > n){//wrong way
return;
}else {
getPaths(n, i +1, j , path, pathList);
getPaths(n, i , j +1, path, pathList);
}
}
I see no indications for obstacles in your question so we can assume there are none.
Note that for an n+1 by n+1 grid, a robot needs to take exactly 2n steps in order to reach the lower right corner. Thus, it cannot make any more than 2n moves.
Let's start with a simpler case: [find all paths to the right down corner]
The robot can make exactly choose(n,2n)= (2n)!/(n!*n!) paths: It only needs to choose which of the 2n moves will be right, with the rest being down (there are exactly n of these).
To generate the possible paths: just generate all binary vectors of size 2n with exactly n 1's. The 1's indicate right moves, the 0's, down moves.
Now, let's expand it to all paths:
First choose the length of the path. To do so, iterate over all possibilities: 0 <= i <= 2n, where i is the length of the path. In this path there are max(0,i-n) <= j <= min(i,n) right steps.
To generate all possibilities, implement the following pseudo-code:
for each i in [0,2n]:
for each j in [max(0,i-n),min(i,n)]:
print all binary vectors of size i with exactly j bits set to 1
Note 1: printing all binary vectors of size i with j bits set to 1 could be computationally expensive. That is expected since there are an exponential number of solutions.
Note 2: For the case i=2n, you get j in [n,n], as expected (the simpler case described above).
https://math.stackexchange.com/questions/104032/finding-points-in-a-grid-with-exactly-k-paths-to-them - look here at my solution. Seems that it is exactly what you need (yes, statements are slightly different, but in general case they are just the same).
This is for if the robot can go 4 directions rather than just 2, but the recursive solution below (in Javascript) works and I've tried to make it as legible as possible:
//first make a function to create the board as an array of arrays
var makeBoard = function(n) {
var board = [];
for (var i = 0; i < n; i++) {
board.push([]);
for (var j = 0; j < n; j++) {
board[i].push(false);
}
}
board.togglePiece = function(i, j) {
this[i][j] = !this[i][j];
}
board.hasBeenVisited = function(i, j) {
return !!this[i][j];
}
board.exists = function(i, j) {
return i < n && i > -1 && j < n && j > -1;
}
board.viablePosition = function(i, j) {
return board.exists(i, j) && !board.hasBeenVisited(i,j);
}
return board;
};
var robotPaths = function(n) {
var numPaths = 0;
//call our recursive function (defined below) with a blank board of nxn, with the starting position as (0, 0)
traversePaths(makeBoard(n), 0, 0);
//define the recursive function we'll use
function traversePaths(board, i, j) {
//BASE CASE: if reached (n - 1, n - 1), count as solution and stop doing work
if (i === (n - 1) && j === (n - 1)) {
numPaths++;
return;
}
//mark the current position as having been visited. Doing this after the check for BASE CASE because you don't want to turn the target position (i.e. when you've found a solution) to true or else future paths will see it as an unviable position
board.togglePiece(i, j);
//RECURSIVE CASE: if next point is a viable position, go there and make the same decision
//go right if possible
if (board.viablePosition(i, j + 1)) {
traversePaths(board, i, j + 1);
}
//go left if possible
if (board.viablePosition(i, j - 1)) {
traversePaths(board, i, j - 1);
}
//go down if possible
if (board.viablePosition(i + 1, j)) {
traversePaths(board, i + 1, j);
}
//go up if possible
if (board.viablePosition(i - 1, j)) {
traversePaths(board, i - 1, j);
}
//reset the board back to the way you found it after you've gone forward so that other paths can see it as a viable position for their routes
board.togglePiece(i, j);
}
return numPaths;
};
A cleaner version:
var robotPaths = function(n, board, i, j) {
board = board || makeBoard(n),
i = i || 0,
j = j || 0;
// If current cell has been visited on this path or doesn't exist, can't go there, so do nothing (no need to return since there are no more recursive calls below this)
if (!board.viablePosition(i, j)) return 0;
// If reached the end, add to numPaths and stop recursing
if (i === (n - 1) && j === (n - 1)) return 1;
// Mark current cell as having been visited for this path
board.togglePiece(i, j);
// Check each of the four possible directions
var numPaths = robotPaths(n, board, i + 1, j) + robotPaths(n, board, i - 1, j) + robotPaths(n, board, i, j + 1) + robotPaths(n, board, i, j - 1);
// Reset current cell so other paths can go there (since board is a pointer to an array that every path is accessing)
board.togglePiece(i, j);
return numPaths;
}
So:
robotPaths(5); //returns 8512
Scenario:
1. Imagine there is NxN zero indexed matrix.
2. Initial position of robot is upper-left corner i.e. (N-1, N-1)
3. Robot wants to reach lower right corner i.e. at (0,0)
Solution:
-- In any possible solution robot will move N rights steps and N down steps to reach (0,0), or we can say that initial robot has permission to move N rights steps and N down steps.
-- When ever robot moves right we reduce its remaining number of right steps by 1, same is for down movement.
-- At every position(except at boundary, where it will have only one option) robot have two options, one is it can go down or other is it can go right.
-- It will terminate when robot will have no remaining down of right steps.
**Below code also have driver method main(), you can change the value of N. N can be >=1
public class RobotPaths {
public static int robotPaths(int down, int right, String path)
{
path = path+ down +","+ right +" ";
if(down==0 && right==0)
{
System.out.println(path);
return 1;
}
int counter = 0;
if(down==0)
counter = robotPaths(down, right-1, path);
else if(right==0)
counter = robotPaths(down-1, right, path);
else
counter = robotPaths(down, right-1, path) + robotPaths(down-1, right, path);
return counter;
}
public static void main(String[] args)
{
int N = 1;
System.out.println("Total possible paths: "+RobotPaths.robotPaths(N-1, N-1, ""));
}
}
If you just need a count of the valid paths:
Let's say you have a matrix n*m matrix and you set all cells to zero and the "offlimit" cells to -1.
You can then solve the problem with dynamic programming:
// a is a matrix with 0s and -1s
// n, m are the dimensions
// M is 10^9-7 incase you have a large matrix
if (a[0][0] == 0) a[0][0] = 1;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (a[i][j] == -1) continue;
if (i > 0) a[i][j] = (a[i][j] + max(a[i-1][j], 0LL)) % M;
if (j > 0) a[i][j] = (a[i][j] + max(a[i][j-1], 0LL)) % M;
}
}
// answer at lower right corner
cout << a[n-1][m-1];
Blazing fast without recursion or bloaty data structures.
NOTE: this was deleted due to being duplicate but since this is the best thread on this topic, I've deleted my answer from elsewhere and will add this here.
Here is c# version (just for reference) to find unique paths (note here is the version which returns number of paths using dynamic programming (memorization - lazy) - Calculating number of moves from top left corner to bottom right with move in any direction) (you may refer to my blog for more details: http://codingworkout.blogspot.com/2014/08/robot-in-grid-unique-paths.html)
Tuple<int, int>[][] GetUniquePaths(int N)
{
var r = this.GetUniquePaths(1, 1, N);
return r;
}
private Tuple<int, int>[][] GetUniquePaths(int row, int column, int N)
{
if ((row == N) && (column == N))
{
var r = new Tuple<int, int>[1][];
r[0] = new Tuple<int, int>[] { new Tuple<int,int>(row, column) };
return r;
}
if ((row > N) || (column > N))
{
return new Tuple<int, int>[0][];
}
var uniquePathsByMovingDown = this.GetUniquePaths(row + 1, column, N);
var uniquePathsByMovingRight = this.GetUniquePaths(row, column + 1, N);
List<Tuple<int, int>[]> paths = this.MergePaths(uniquePathsByMovingDown,
row, column).ToList();
paths.AddRange(this.MergePaths(uniquePathsByMovingRight, row, column));
return paths.ToArray();
}
where
private Tuple<int, int>[][] MergePaths(Tuple<int, int>[][] paths,
int row, int column)
{
Tuple<int, int>[][] mergedPaths = new Tuple<int, int>[paths.Length][];
if (paths.Length > 0)
{
Assert.IsTrue(paths.All(p => p.Length > 0));
for (int i = 0; i < paths.Length; i++)
{
List<Tuple<int, int>> mergedPath = new List<Tuple<int, int>>();
mergedPath.Add(new Tuple<int, int>(row, column));
mergedPath.AddRange(paths[i]);
mergedPaths[i] = mergedPath.ToArray();
}
}
return mergedPaths;
}
Unit Tests
[TestCategory(Constants.DynamicProgramming)]
public void RobotInGridTests()
{
int p = this.GetNumberOfUniquePaths(3);
Assert.AreEqual(p, 6);
int p1 = this.GetUniquePaths_DP_Memoization_Lazy(3);
Assert.AreEqual(p, p1);
var p2 = this.GetUniquePaths(3);
Assert.AreEqual(p1, p2.Length);
foreach (var path in p2)
{
Debug.WriteLine("===================================================================");
foreach (Tuple<int, int> t in path)
{
Debug.Write(string.Format("({0}, {1}), ", t.Item1, t.Item2));
}
}
p = this.GetNumberOfUniquePaths(4);
Assert.AreEqual(p, 20);
p1 = this.GetUniquePaths_DP_Memoization_Lazy(4);
Assert.AreEqual(p, p1);
p2 = this.GetUniquePaths(4);
Assert.AreEqual(p1, p2.Length);
foreach (var path in p2)
{
Debug.WriteLine("===================================================================");
foreach (Tuple<int, int> t in path)
{
Debug.Write(string.Format("({0}, {1}), ", t.Item1, t.Item2));
}
}
}
Here is a full implementation that works for both rectangular and square grids. I will leave you to figure out how to take care of the excess "=>" at the end of each path.
import java.util.Arraylist;
public class PrintPath
{
static ArrayList<String> paths = new ArrayList<String>();
public static long getUnique(int m, int n, int i, int j, String pathlist)
{
pathlist += ("(" + i + ", " + (j) + ") => ");
if(m == i && n == j)
{
paths.add(pathlist);
}
if( i > m || j > n)
{
return 0;
}
return getUnique(m, n, i+1, j, pathlist)+getUnique(m, n, i, j+1, pathlist);
}
public static void printPaths()
{
int count = 1;
System.out.println("There are "+paths.size() + " unique paths: \n");
for (int i = paths.size()-1; i>=0; i--)
{
System.out.println( "path " + count + ": " + paths.get(i));
count++;
}
}
public static void main(String args[])
{
final int start_Point = 1;
int grid_Height = 2;
int grid_Width = 2;
getUnique(grid_Height, grid_Width, start_Point, start_Point, "");
printPaths();
}
}
Below is the code in Java to count all the possible paths from top left corner to bottom right corner of a NXN matrix.
public class paths_in_matrix {
/**
* #param args
*/
static int n=5;
private boolean[][] board=new boolean[n][n];
int numPaths=0;
paths_in_matrix(){
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
board[i][j]=false;
}
}
}
private void togglePiece(int i,int j){
this.board[i][j]=!this.board[i][j];
}
private boolean hasBeenVisited(int i,int j){
return this.board[i][j];
}
private boolean exists(int i,int j){
return i < n && i > -1 && j < n && j > -1;
}
private boolean viablePosition(int i,int j){
return exists(i, j) && !hasBeenVisited(i,j);
}
private void traversePaths(int i,int j){
//BASE CASE: if reached (n - 1, n - 1), count as path and stop.
if (i == (n - 1) && j == (n - 1)) {
this.numPaths++;
return;
}
this.togglePiece(i, j);
//RECURSIVE CASE: if next point is a viable position, go there and make the same decision
//go right if possible
if (this.viablePosition(i, j + 1)) {
traversePaths(i, j + 1);
}
//go left if possible
if (this.viablePosition(i, j - 1)) {
traversePaths( i, j - 1);
}
//go down if possible
if (this.viablePosition(i + 1, j)) {
traversePaths( i + 1, j);
}
//go up if possible
if (this.viablePosition(i - 1, j)) {
traversePaths(i - 1, j);
}
//reset the board back to the way you found it after you've gone forward so that other paths can see it as a viable position for their routes
this.togglePiece(i, j);
}
private int robotPaths(){
traversePaths(0,0);
return this.numPaths;
}
public static void main(String[] args) {
paths_in_matrix mat=new paths_in_matrix();
System.out.println(mat.robotPaths());
}
}
Here you go (python):
def numPathsFromULtoRD(m,n):
return factorial(m+n-2)//(factorial(m-1)*factorial(n-1))
def solution(m,n):
result = 0
for i in range(m):
for j in range(n):
if i == 0 and j == 0:
continue
result += numPathsFromULtoRD(i+1,j+1)
return result
int N;
function num_paths(intx,int y)
{
int[][] arr = new int[N][N];
arr[N-1][N-1] = 0;
for(int i =0;i<N;i++)
{
arr[N-1][i]=1;
arr[i][N-1]=1;
}
for(int i = N-2;i>=0;i--)
{
for(int j=N-2;j>=0;j--)
{
arr[i][j]= arr[i+1][j]+arr[i][j+1];
}
}
return arr[0][0];
}

Categories