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.
We can conclude that there are 6 distinct paths in this grid. Now take a look at this 8x8 grid: If you try to count the number of paths on this grid, if will take you quite some time. We will need some more intelligent, mathematical approach.
For a 4x4 grid I need to make 6 moves. There are 64 possible paths.
Starting in the top left corner of a 2 × 2 grid, there are 6 routes (without backtracking) to the bottom right corner.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With