How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid


Let’s see this question: If Jack starts at A, and he can only travels one move at a time to the north or east, and he cannot go back. If he needs to travel through B, and finally reach C, how many ways are there for him to complete his journey?

travel-from-a-to-b-to-c How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle

travel-from-a-to-b-to-c

Brute-force?

In theory, you can write a program to count each possible path from A to C, then, only those paths through B are valid. This could take ages. For example, if A and B are separated by x steps horizontally and y steps vertically (x steps east and y steps north), the total number of paths is:

tex_8bd19f28227fa25be0bb077d7ee7a9e4 How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle or
tex_d5f725c0b44d70bdc6ea1d5e3add755d How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle

This reads: the number of ways to choose x or y items from (x + y) items. In this case, the x=8 and y=9, which makes the bruteforce inefficient.

Pure Math Solution

A better way is to simplify the problem into two steps. First is to travel from A to B and the second step is to travel from B to C, thus, if we denote f(a, b) the number of paths from a to b, then the total number is:

tex_08d0d996cdb4c348af7e1f435eff9a0e How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle .

According to the above, tex_70db27f2498262158da715c5e03965c4 How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle and tex_5adb5f7307dff7e63a9f9fd389030898 How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid algorithms dynamic programming math php puzzle which sums up to 8820.

Recursion

Let’s write a function f(x, y) which returns the number of different paths for x steps east and y steps north.

1
2
3
4
5
6
function f($x, $y) {
  if (($x == 0) || ($y == 0)) {
    return 1;
  }
  return f($x - 1, $y) + f($x, $y - 1); // we can take either 1 step north or 1 step east.
}
function f($x, $y) {
  if (($x == 0) || ($y == 0)) {
    return 1;
  }
  return f($x - 1, $y) + f($x, $y - 1); // we can take either 1 step north or 1 step east.
}

And the answer is just:

1
echo f(3, 4) * f(5, 5); // 8820
echo f(3, 4) * f(5, 5); // 8820

For each recursive call, there are two choices: 1 step north or 1 step east, so the answer is just to add these two (decompose into two smaller problems). The exiting conditions are when the offset is zero (step count is zero), this is when the answer should be returned as 1.

Dynamic Programming (Memorization)

The recursion is straightforward. However, it does not work well if the input is large, as a lot of intermediate results are computed again and again. You can memorize the intermediate results, which will speed up the computation (each f(x,y) is only computed once because next time the result will be fetched from memory):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$cache = array();
 
function f($x, $y) {
  global $cache;
  if (($x == 0) || ($y == 0)) {
    return 1;
  }
  $key = $x.' '.$y; 
  if (isset($cache[$key])) { // has the result been computed?
    return $cache[$key];
  } 
  $sol = f($x - 1, $y) + f($x, $y - 1);
  $cache[$key] = $sol; // store the result
  return $sol;
}
$cache = array();

function f($x, $y) {
  global $cache;
  if (($x == 0) || ($y == 0)) {
    return 1;
  }
  $key = $x.' '.$y; 
  if (isset($cache[$key])) { // has the result been computed?
    return $cache[$key];
  } 
  $sol = f($x - 1, $y) + f($x, $y - 1);
  $cache[$key] = $sol; // store the result
  return $sol;
}

The next improvement to improve this Dynamic Programming DP implementation is to use the iteration, which avoids the recursion. This is computed bottom-up direction.

1
2
3
4
5
6
7
8
9
10
11
function f($x, $y) {
  $ans = array();
  for ($i = 0; $i <= $x; ++ $i) $ans[$i][0] = 1;
  for ($i = 0; $i <= $y; ++ $i) $ans[0][$i] = 1;
  for ($i = 1; $i <= $x; ++ $i) {
    for ($j = 1; $j <= $y; ++ $j) {
      $ans[$i][$j] = $ans[$i - 1][$j] + $ans[$i][$j - 1]; 
    }
  }
  return $ans[$x][$y];
}
function f($x, $y) {
  $ans = array();
  for ($i = 0; $i <= $x; ++ $i) $ans[$i][0] = 1;
  for ($i = 0; $i <= $y; ++ $i) $ans[0][$i] = 1;
  for ($i = 1; $i <= $x; ++ $i) {
    for ($j = 1; $j <= $y; ++ $j) {
      $ans[$i][$j] = $ans[$i - 1][$j] + $ans[$i][$j - 1]; 
    }
  }
  return $ans[$x][$y];
}

This runs at complexity O(xy) as well as the space complexity (need to declare a 2-dimensional array). Is this optimial? No, you can further reduce the complexity to O(y).

Algorithms to Walk in a Grid

Here are some posts on the path counting or probability on a Grid:

–EOF (The Ultimate Computing & Technology Blog) —

GD Star Rating
loading...
993 words
Last Post: BTC Hard-Fork via C program (Linux) and How to Claim BCC?
Next Post: Software Engineer Interview Question - How to Improve Dynamic Programming Space Complexity?

The Permanent URL is: How Many Ways from A to C via B? Counting the Unique Paths Walking in a Grid

Leave a Reply