---
# System prepended metadata

title: backtracking

---

# backtracking

- only enter a promising spot, so I need to :
    - check before initial call
    - check before every recursive/fan-out call
- check termination at the beginning of backtrack()
- add to path/visited before fanout for-loop
- remove from path/visited after fanout for-loop
    
```python=
def soln(grid, word):
    m = len(grid)
    n = len(grid[0])
    def inside(i, j):
        return (0 <= i < m and 0 <= j < n)

    def btrack (i, j, k):
        # Guaranteed this (i,j) matchs the letter

        # Termination: Record/return the result. Stop go further
        # If matched and already the last one -> full matched -> dump the path
        if k == len(word) - 1:
            ans_li.append(path + [(i, j)])  # Make a hard copy.
            return

        # Not yet full matched.
        # So, all guys in `path` and `visited` are always legal and promising
        path.append((i, j))
        visited.add((i, j))

        # fanout
        for newi, newj in [(i + 1, j), (i, j + 1)]:
            # only try on legal and promising spots
            if ((newi, newj) not in visited and inside(newi, newj) and
                grid[newi][newj] == word[k + 1]):  # https://google.github.io/styleguide/pyguide.html#32-line-length
                btrack(newi, newj, k + 1)

        path.pop()
        visited.remove((i, j))
        return

    ans_li = []
    path = []
    visited = set()

    for i in range(m):
        for j in range(n):
            # Always ensure btrack() is entering a promising spot
            # 1) inside: yes
            # 2) visited: no
            # 3) letter matched: yes
            if grid[i][j] == word[0]:
                btrack(i, j, 0)

    return ans_li

grid1 = [
    ['c', 'c', 't', 'n', 'a', 'x'],
    ['c', 'c', 'a', 't', 'n', 't'],
    ['a', 'c', 'n', 'n', 't', 't'],
    ['t', 'n', 'i', 'i', 'p', 'p'],
    ['a', 'o', 'o', 'o', 'a', 'a'],
    ['s', 'a', 'a', 'a', 'o', 'o'],
    ['k', 'a', 'i', 'o', 'k', 'i'],
]
word1 = "catnip"
word2 = "cccc"
word3 = "s"
word4 = "ant"
word5 = "aoi"
word6 = "ki"
word7 = "aaoo"
word8 = "ooo"
word9 = "a"



"""
find_word_location(grid1, word1) => [ (1, 1), (1, 2), (1, 3), (2, 3), (3, 3), (3, 4) ]
find_word_location(grid1, word2) =>
       [(0, 0), (1, 0), (1, 1), (2, 1)]
    OR [(0, 0), (0, 1), (1, 1), (2, 1)]
find_word_location(grid1, word3) => [(5, 0)]
find_word_location(grid1, word4) => [(0, 4), (1, 4), (2, 4)] OR [(0, 4), (1, 4), (1, 5)]
find_word_location(grid1, word5) => [(4, 5), (5, 5), (6, 5)]
find_word_location(grid1, word6) => [(6, 4), (6, 5)]
find_word_location(grid1, word7) => [(5, 2), (5, 3), (5, 4), (5, 5)]
find_word_location(grid1, word8) => [(4, 1), (4, 2), (4, 3)]
find_word_location(grid2, word9) => [(0, 0)]
"""
grid2 = [['a']]

print(soln(grid1, word1))
print(soln(grid1, word2))
print(soln(grid1, word3))
print(soln(grid1, word4))
print(soln(grid1, word5))
print(soln(grid1, word6))
print(soln(grid1, word7))
print(soln(grid1, word8))

print(soln(grid2, word9))

print(soln(grid1, word9))
print(soln(grid1, "qwert"))

```