diff --git a/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.go b/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.go new file mode 100644 index 0000000..e8a205a --- /dev/null +++ b/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.go @@ -0,0 +1,63 @@ +package main + +import "fmt" + +func pacificAtlantic(matrix [][]int) [][]int { + if len(matrix) == 0 || len(matrix[0]) == 0 { + return [][]int{} + } + + rows, cols := len(matrix), len(matrix[0]) + // here, rather than use a Set of all coord pairs like in our TS + // implementation, we create a grid representing all cells in matrix + pacific := make([][]bool, rows) + atlantic := make([][]bool, rows) + for i := range pacific { + pacific[i] = make([]bool, cols) + atlantic[i] = make([]bool, cols) + } + for i := 0; i < rows; i++ { + dfs(matrix, pacific, i, 0) + dfs(matrix, atlantic, i, cols-1) + } + for i := 0; i < cols; i++ { + dfs(matrix, pacific, 0, i) + dfs(matrix, atlantic, rows-1, i) + } + + result := [][]int{} + for i := 0; i < rows; i++ { + for j := 0; j < cols; j++ { + if pacific[i][j] && atlantic[i][j] { + result = append(result, []int{i, j}) + } + } + } + + return result + +} + +func dfs(matrix [][]int, ocean [][]bool, r, c int) { + ocean[r][c] = true + directions := [][]int{{-1, 0}, {1, 0}, {0, -1}, {0, 1}} + for _, dir := range directions { + x, y := r+dir[0], c+dir[1] + if x >= 0 && x < len(matrix) && y >= 0 && y < len(matrix[0]) && !ocean[x][y] && matrix[x][y] >= matrix[r][c] { + dfs(matrix, ocean, x, y) + } + } +} + +func main() { + input := [][]int{ + {1, 2, 2, 3, 5}, + {1, 2, 3, 4, 4}, + {2, 4, 5, 3, 1}, + {6, 7, 1, 4, 5}, + {5, 1, 1, 2, 4}, + } + + result := pacificAtlantic(input) + fmt.Println(result) +} diff --git a/Pacific Atlantic Water Flow 417.py b/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.py similarity index 100% rename from Pacific Atlantic Water Flow 417.py rename to Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.py diff --git a/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.ts b/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.ts new file mode 100644 index 0000000..9e0bb8a --- /dev/null +++ b/Pacific Atlantic Water Flow/Pacific Atlantic Water Flow 417.ts @@ -0,0 +1,83 @@ +const input = [ + [1, 2, 2, 3, 5], + [1, 2, 3, 4, 4], + [2, 4, 5, 3, 1], + [6, 7, 1, 4, 5], + [5, 1, 1, 2, 4], +]; + +// each number represents an elevation. +// return all of the indexes i,j which flow water down to both oceans. +// for example, position 0,5 is a 5. This is already touching both oceans. +// position 2,2 is a 5. This flows water up to 3, then up to 2, then up to pacific. +// it also flows down to 1, then down to 1, then down to pacific. +// in this case, both positions 0,5 and 2,2 are valid, and should be returned. + +// first we look at all cells which immediately touch the pacific ocean. +// we do a BFS to see any adjacent cells which are > the cell they touch, and continue the process. +// we do the same for any cells immediately touching the atlantic ocean. +// the dataset we return will be an intersection of all cells which touch both atlantic and pacific. + +function pacificAtlantic(heights: number[][]): number[][] { + const rows = heights.length; + const cols = heights[0].length; + const pacific = new Set(); + const atlantic = new Set(); + const output: number[][] = []; + + // fill pacific stack with border cells that can reach the pacific + // fill atlantic stack with border cells that can reach the atlantic + for (let c = 0; c < cols; c++) { + dfs(heights, 0, c, heights[0][c], pacific); + dfs(heights, rows - 1, c, heights[rows - 1][c], atlantic); + } + + for (let r = 0; r < rows; r++) { + dfs(heights, r, 0, heights[r][0], pacific); + dfs(heights, r, cols - 1, heights[r][cols - 1], atlantic); + } + + // intersection of pacific keys which reach pacific and atlantic keys which reach atlantic + for (let r = 0; r < rows; r++) { + for (let c = 0; c < cols; c++) { + const key = encode(r, c); + if (pacific.has(key) && atlantic.has(key)) { + output.push([r, c]); + } + } + } + + return output; +} + +function dfs( + grid: number[][], + r: number, + c: number, + max: number, + visited: Set +): void { + const rows = grid.length; + const cols = grid[0].length; + + if ( + visited.has(encode(r, c)) || + r < 0 || + r >= rows || + c < 0 || + c >= cols || + grid[r][c] < max + ) { + return; + } + visited.add(encode(r, c)); + + dfs(grid, r + 1, c, grid[r][c], visited); + dfs(grid, r - 1, c, grid[r][c], visited); + dfs(grid, r, c + 1, grid[r][c], visited); + dfs(grid, r, c - 1, grid[r][c], visited); +} + +function encode(x: number, y: number) { + return `${x},${y}`; +}