21

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.

Periastron
  • 663
  • 2
  • 10
  • 15
  • 5
    "how many path are there?", this is a mathematical not programming question. And what will you implement in Java? Count the number of paths? Output all the paths themselves? Is this a homework? – Ali Ferhat Feb 02 '12 at 01:04
  • @Ali : This is an interview question. And this is the exact text for the question, hence the difficulty in understanding it. For now I am trying to solve how to find all the paths to reach the bottom-right corner and the program would print those paths. – Periastron Feb 02 '12 at 01:20
  • 1
    I cannot see any effort on your part that you actually tried to solve the problem, so just two suggestions in case you are a beginner: read a chapter on recursion in a good beginner level data structures / algorithms book and think about how you could solve the problem using recursion. Then, if run-time efficiency is important, read a chapter on dynamic programming and think how you could apply what you've learned to the problem at hand. – Ali Ferhat Feb 02 '12 at 01:28
  • 1
    @Ali - This is an O(1) operation because of the constraints "only right or down". – Travis J Feb 02 '12 at 01:29
  • 1
    Before you read the answer TravisJ has given, Periastron, I would recommend you try working out the pattern for this yourself. Why not see how many paths you can make on a 2x2 grid? A 3x3? Now, see if you can find some process or relationship between how many paths you get and *N*. Try mucking around with it and make some observations, and when you've made some headway or even found a solution, *then* come back and see the answer. Because really, as it is now, all you've asked is whether you can have code. – blahman Feb 02 '12 at 01:32
  • 1
    In regards to the update, this is definitely more complex because each path must now be defined and therefore constructed. Visiting each path will take very long, O(n^n), probably not possible on grids larger than 15 without waiting for a very, very, long time. – Travis J Feb 02 '12 at 01:36
  • @Blahman I already tried the 2x2 and 3x3 scenario and solved it to some extent. Found the general formula for finding the number of paths, before I posted the question. But somewhere in the middle I got little confused and wanted to know how to approach such a problem. Haven't read any of the solutions yet. My intention was not to just ask for code. I want to understand the logic behind it so that I could apply it to this and similar problems. – Periastron Feb 02 '12 at 01:37
  • In this case, if you can find the general formula I think you'd be fine. It just sounded like you were after getting code for how to find the number of paths. Your update to the question, as the other posters have noted, makes it significantly more difficult and I don't think you can get an efficient solution to print every path. TravisJ's explanation for how many paths there are is pretty sufficient though ^^ – blahman Feb 02 '12 at 01:41
  • total paths? or only paths to reach the down down corner? [In other words, can the robot "stop" if there is still "legal" move it can make]? – amit Feb 02 '12 at 12:26
  • @TravisJ Are you sure we can do it in O(1)? The best I can think of in case of finding the number of ways of reaching the right most cell is O(n) – bashrc Dec 07 '12 at 15:02
  • @bashrc - That comment was in relation to an earlier version of this question. O(1) was no longer possible after the update was made. – Travis J Dec 07 '12 at 18:12
  • 1
    Sounds like question 9.2 on page 109 of "Cracking the Coding Interview" (Fifth Edition) by Gale Laakmann McDowell. Is that the original source? – Adam Monsen Jan 29 '13 at 18:14
  • If it's an interview question, be aware that they might ask you an ongoing question, like: "We have this somewhat similar problem, you described how you solved the old one, now, what would you change in your old solution to...". At least that's what I'd do, especially if I gave you enough time to search for an answer on the web. – Aziuth Dec 05 '16 at 16:37

11 Answers11

34
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);
    }
}
hoju
  • 28,392
  • 37
  • 134
  • 178
Ethan
  • 481
  • 1
  • 4
  • 4
  • The question was to find all the paths, **not to find the number of paths**. You can have a closed formula to get the number of them for each length (I described this formula in my answer). – amit Nov 07 '12 at 22:24
  • @Ethan , what if the robot goes to all the directions (left and up also)? then how we can get the number of possible paths?! – secret Jan 31 '16 at 20:46
19

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).

Community
  • 1
  • 1
amit
  • 175,853
  • 27
  • 231
  • 333
2

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
Muhammad Naqvi
  • 111
  • 1
  • 2
2

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).

Community
  • 1
  • 1
OleGG
  • 8,589
  • 1
  • 28
  • 34
1

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, ""));

}

}

Neo
  • 79
  • 2
  • 6
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.

elnygren
  • 5,000
  • 4
  • 20
  • 31
0

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));
                }
            }
        }
Community
  • 1
  • 1
Dreamer
  • 3,371
  • 2
  • 34
  • 50
0

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

    }

}
-1

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

}
Shashi Kiran
  • 367
  • 3
  • 9
-1

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
eral
  • 123
  • 1
  • 16
-2
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];
 }
everconfusedGuy
  • 2,709
  • 27
  • 43
  • 1
    To calculate the number of paths there is no need for this code, since there is a very simple combinatorial formula. The question asks to print individual paths one by one, not find the number of them. – Ali Ferhat Feb 02 '12 at 12:30