From 750ace667a6c87ec75e3bfe4d257a80050f8415b Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 17:22:23 -0400 Subject: [PATCH 01/11] added recursive dfs backtracking for count paths with doctests --- matrix/matrix_dfs.py | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 matrix/matrix_dfs.py diff --git a/matrix/matrix_dfs.py b/matrix/matrix_dfs.py new file mode 100644 index 000000000000..c7057d54a4b0 --- /dev/null +++ b/matrix/matrix_dfs.py @@ -0,0 +1,31 @@ +def dfs(grid, r, c, visit): + """ + Recursive Backtracking Depth First Search Algorithm + + Starting from top left of a matrix, count the number of paths that can reach the bottom right of a matrix. + 1 represents a block (inaccessible) + 0 represents a valid space (accessible) + + >>> startRow = 0 + >>> startCol = 0 + >>> visited = set() + >>> grid = [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0]] + >>> dfs(grid, startRow, startCol, visited) + 2 + """ + ROWS, COLS = len(grid), len(grid[0]) + if min(r, c) < 0 or r == ROWS or c == COLS or (r, c) in visit or grid[r][c] == 1: + return 0 + if r == ROWS - 1 and c == COLS - 1: + return 1 + + visit.add((r, c)) + + count = 0 + count += dfs(grid, r + 1, c, visit) + count += dfs(grid, r - 1, c, visit) + count += dfs(grid, r, c + 1, visit) + count += dfs(grid, r, c - 1, visit) + + visit.remove((r, c)) + return count From 4984eb8df2b542ca6500ea022e73d46dc65d9a99 Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 17:30:11 -0400 Subject: [PATCH 02/11] fixed doc testing --- matrix/{matrix_dfs.py => count_paths.py} | 5 +++++ 1 file changed, 5 insertions(+) rename matrix/{matrix_dfs.py => count_paths.py} (93%) diff --git a/matrix/matrix_dfs.py b/matrix/count_paths.py similarity index 93% rename from matrix/matrix_dfs.py rename to matrix/count_paths.py index c7057d54a4b0..2d88d2969553 100644 --- a/matrix/matrix_dfs.py +++ b/matrix/count_paths.py @@ -29,3 +29,8 @@ def dfs(grid, r, c, visit): visit.remove((r, c)) return count + +if __name__ == "__main__": + import doctest + + doctest.testmod() \ No newline at end of file From 540351d46f618e1dd5733f10c49e9ab72cf7e40e Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 17:40:43 -0400 Subject: [PATCH 03/11] added type hints --- matrix/count_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 2d88d2969553..43e496cc4c24 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -1,4 +1,4 @@ -def dfs(grid, r, c, visit): +def dfs(grid : list(list(int)), r: int, c: int, visit: set()) -> int: """ Recursive Backtracking Depth First Search Algorithm From 578b7b8d0657610b6ea17e05b36a55ba485dc82a Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 17:43:43 -0400 Subject: [PATCH 04/11] redefined r as row, c as col --- matrix/count_paths.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 43e496cc4c24..71871d6c8e54 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -1,4 +1,4 @@ -def dfs(grid : list(list(int)), r: int, c: int, visit: set()) -> int: +def dfs(grid : list(list(int)), row: int, col: int, visit: set()) -> int: """ Recursive Backtracking Depth First Search Algorithm @@ -14,20 +14,20 @@ def dfs(grid : list(list(int)), r: int, c: int, visit: set()) -> int: 2 """ ROWS, COLS = len(grid), len(grid[0]) - if min(r, c) < 0 or r == ROWS or c == COLS or (r, c) in visit or grid[r][c] == 1: + if min(row, col) < 0 or row == ROWS or col == COLS or (row, col) in visit or grid[row][col] == 1: return 0 - if r == ROWS - 1 and c == COLS - 1: + if row == ROWS - 1 and col == COLS - 1: return 1 - visit.add((r, c)) + visit.add((row, col)) count = 0 - count += dfs(grid, r + 1, c, visit) - count += dfs(grid, r - 1, c, visit) - count += dfs(grid, r, c + 1, visit) - count += dfs(grid, r, c - 1, visit) + count += dfs(grid, row + 1, col, visit) + count += dfs(grid, row - 1, col, visit) + count += dfs(grid, row, col + 1, visit) + count += dfs(grid, row, col - 1, visit) - visit.remove((r, c)) + visit.remove((row, col)) return count if __name__ == "__main__": From 3da452caedcc5a37fe688a0a6e0ab8cf642e8fd1 Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 18:13:16 -0400 Subject: [PATCH 05/11] fixed naming conventions, ran mypy, only tests that didn't pass were using List[], rathan list() --- matrix/count_paths.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 71871d6c8e54..d4759f18de7b 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -6,17 +6,17 @@ def dfs(grid : list(list(int)), row: int, col: int, visit: set()) -> int: 1 represents a block (inaccessible) 0 represents a valid space (accessible) - >>> startRow = 0 - >>> startCol = 0 + >>> start_row = 0 + >>> start_col = 0 >>> visited = set() >>> grid = [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0]] - >>> dfs(grid, startRow, startCol, visited) + >>> dfs(grid, start_row, start_col, visited) 2 """ - ROWS, COLS = len(grid), len(grid[0]) - if min(row, col) < 0 or row == ROWS or col == COLS or (row, col) in visit or grid[row][col] == 1: + row_length, col_length = len(grid), len(grid[0]) + if min(row, col) < 0 or row == row_length or col == col_length or (row, col) in visit or grid[row][col] == 1: return 0 - if row == ROWS - 1 and col == COLS - 1: + if row == row_length - 1 and col == col_length - 1: return 1 visit.add((row, col)) From 67e03af4f9681d78bcb43e57b870203b3e37b93c Mon Sep 17 00:00:00 2001 From: J Date: Sat, 22 Oct 2022 19:38:43 -0400 Subject: [PATCH 06/11] added another doctest, as well as a explanation above --- matrix/count_paths.py | 50 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index d4759f18de7b..a8cc783e9afa 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -1,4 +1,26 @@ -def dfs(grid : list(list(int)), row: int, col: int, visit: set()) -> int: +""" +Given a grid, where you start from the top left position [0, 0], +you want to find how many paths you can take to get to the bottom right position. + +start here -> 0 0 0 0 + 1 1 0 0 + 0 0 0 1 + 0 1 0 0 <- finish here +how many 'distinct' paths can you take to get to the finish? +Using a recursive depth-first search algorithm below, you are able to +find the number of distinct unique paths (count). + +'*' will demostrate a path +In the example above, there are two distinct paths: +1. 2. + * * * 0 * * * * + 1 1 * 0 1 1 * * + 0 0 * 1 0 0 * 1 + 0 1 * * 0 1 * * +""" + + +def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: """ Recursive Backtracking Depth First Search Algorithm @@ -6,15 +28,36 @@ def dfs(grid : list(list(int)), row: int, col: int, visit: set()) -> int: 1 represents a block (inaccessible) 0 represents a valid space (accessible) + 0 0 0 0 + 1 1 0 0 + 0 0 0 1 + 0 1 0 0 >>> start_row = 0 >>> start_col = 0 >>> visited = set() >>> grid = [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0]] >>> dfs(grid, start_row, start_col, visited) 2 + + 0 0 0 0 0 + 0 1 1 1 0 + 0 1 1 1 0 + 0 0 0 0 0 + >>> start_row = 0 + >>> start_col = 0 + >>> visited = set() + >>> grid = [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]] + >>> dfs(grid, start_row, start_col, visited) + 2 """ row_length, col_length = len(grid), len(grid[0]) - if min(row, col) < 0 or row == row_length or col == col_length or (row, col) in visit or grid[row][col] == 1: + if ( + min(row, col) < 0 + or row == row_length + or col == col_length + or (row, col) in visit + or grid[row][col] == 1 + ): return 0 if row == row_length - 1 and col == col_length - 1: return 1 @@ -30,7 +73,8 @@ def dfs(grid : list(list(int)), row: int, col: int, visit: set()) -> int: visit.remove((row, col)) return count + if __name__ == "__main__": import doctest - doctest.testmod() \ No newline at end of file + doctest.testmod() From 173d05cb294e61334df275b84a27907020b129e5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 22 Oct 2022 23:40:29 +0000 Subject: [PATCH 07/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- matrix/count_paths.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index a8cc783e9afa..02c81128f510 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -7,16 +7,16 @@ 0 0 0 1 0 1 0 0 <- finish here how many 'distinct' paths can you take to get to the finish? -Using a recursive depth-first search algorithm below, you are able to -find the number of distinct unique paths (count). +Using a recursive depth-first search algorithm below, you are able to +find the number of distinct unique paths (count). '*' will demostrate a path In the example above, there are two distinct paths: 1. 2. * * * 0 * * * * - 1 1 * 0 1 1 * * + 1 1 * 0 1 1 * * 0 0 * 1 0 0 * 1 - 0 1 * * 0 1 * * + 0 1 * * 0 1 * * """ From 4252ecb0486709d0fa947ded76fb2fdff94472d0 Mon Sep 17 00:00:00 2001 From: Jason Devers <74424054+jdevers1@users.noreply.github.com> Date: Sat, 22 Oct 2022 21:14:47 -0400 Subject: [PATCH 08/11] Update matrix/count_paths.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- matrix/count_paths.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 02c81128f510..59f8f9a03fbe 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -24,7 +24,8 @@ def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: """ Recursive Backtracking Depth First Search Algorithm - Starting from top left of a matrix, count the number of paths that can reach the bottom right of a matrix. + Starting from top left of a matrix, count the number of + paths that can reach the bottom right of a matrix. 1 represents a block (inaccessible) 0 represents a valid space (accessible) From 02093180d29f974f9d563230ca745ac0de89daa4 Mon Sep 17 00:00:00 2001 From: Jason Devers <74424054+jdevers1@users.noreply.github.com> Date: Sat, 22 Oct 2022 21:14:53 -0400 Subject: [PATCH 09/11] Update matrix/count_paths.py Co-authored-by: Chris O <46587501+ChrisO345@users.noreply.github.com> --- matrix/count_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 59f8f9a03fbe..6d4c05e1b4f2 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -10,7 +10,7 @@ Using a recursive depth-first search algorithm below, you are able to find the number of distinct unique paths (count). -'*' will demostrate a path +'*' will demonstrate a path In the example above, there are two distinct paths: 1. 2. * * * 0 * * * * From e0ffc4661c8953714e6fdf9d662122fe7acee041 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 23 Oct 2022 01:15:41 +0000 Subject: [PATCH 10/11] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- matrix/count_paths.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 6d4c05e1b4f2..265662679bc8 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -24,7 +24,7 @@ def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: """ Recursive Backtracking Depth First Search Algorithm - Starting from top left of a matrix, count the number of + Starting from top left of a matrix, count the number of paths that can reach the bottom right of a matrix. 1 represents a block (inaccessible) 0 represents a valid space (accessible) From 72891f9b4dc3eb498a44209585a7b78418d5c78f Mon Sep 17 00:00:00 2001 From: Chris O <46587501+ChrisO345@users.noreply.github.com> Date: Sun, 30 Oct 2022 18:09:17 +1300 Subject: [PATCH 11/11] Apply suggestions from code review Co-authored-by: Caeden Perelli-Harris --- matrix/count_paths.py | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/matrix/count_paths.py b/matrix/count_paths.py index 265662679bc8..4861ad5fd0aa 100644 --- a/matrix/count_paths.py +++ b/matrix/count_paths.py @@ -20,7 +20,7 @@ """ -def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: +def depth_first_search(grid: list[list[int]], row: int, col: int, visit: set) -> int: """ Recursive Backtracking Depth First Search Algorithm @@ -33,22 +33,16 @@ def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: 1 1 0 0 0 0 0 1 0 1 0 0 - >>> start_row = 0 - >>> start_col = 0 - >>> visited = set() >>> grid = [[0, 0, 0, 0], [1, 1, 0, 0], [0, 0, 0, 1], [0, 1, 0, 0]] - >>> dfs(grid, start_row, start_col, visited) + >>> depth_first_search(grid, 0, 0, set()) 2 0 0 0 0 0 0 1 1 1 0 0 1 1 1 0 0 0 0 0 0 - >>> start_row = 0 - >>> start_col = 0 - >>> visited = set() >>> grid = [[0, 0, 0, 0, 0], [0, 1, 1, 1, 0], [0, 1, 1, 1, 0], [0, 0, 0, 0, 0]] - >>> dfs(grid, start_row, start_col, visited) + >>> depth_first_search(grid, 0, 0, set()) 2 """ row_length, col_length = len(grid), len(grid[0]) @@ -66,10 +60,10 @@ def dfs(grid: "list[list[int]]", row: int, col: int, visit: set) -> int: visit.add((row, col)) count = 0 - count += dfs(grid, row + 1, col, visit) - count += dfs(grid, row - 1, col, visit) - count += dfs(grid, row, col + 1, visit) - count += dfs(grid, row, col - 1, visit) + count += depth_first_search(grid, row + 1, col, visit) + count += depth_first_search(grid, row - 1, col, visit) + count += depth_first_search(grid, row, col + 1, visit) + count += depth_first_search(grid, row, col - 1, visit) visit.remove((row, col)) return count