Guest User

depth first search - python

a guest
Apr 22nd, 2024
84
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 3.92 KB | Source Code | 0 0
  1. import re
  2.  
  3. def find_word(board, word):
  4.     side_len_board = len(board[0])
  5.  
  6.     # pad the board with zeros at the front and back so that my index lookup method does not go out of bounds
  7.     board_padded_front = [['0' for i in range(side_len_board)]] * 2
  8.     board_padded_front += board
  9.     padding_back = [['0' for i in range(side_len_board)]] * 2
  10.     board_padded = board_padded_front + padding_back
  11.  
  12.     # rollup of board into single string for easier checkup later
  13.     board_string = ''
  14.     for row in board_padded:
  15.         s = ''.join(row)
  16.         board_string += s
  17.  
  18.     # Return early if a character of the word is not in the board at all
  19.     if not all(c in board_string for c in word):
  20.         return False
  21.     if len(word)==1:
  22.         return word in board_string
  23.  
  24.     # find the start indices of the first character in the word
  25.     start_idxes = [m.start() for m in re.finditer(word[0], board_string)]
  26.     for idx in start_idxes:
  27.         if depth_first_search(board_string, side_len_board, word[1:], idx):
  28.             return True
  29.     return False
  30.  
  31. def get_adjacent_indices(start_idx, side_len_board):
  32.     return (start_idx - side_len_board - 1,
  33.             start_idx - side_len_board,
  34.             start_idx - side_len_board + 1,
  35.             start_idx - 1,
  36.             start_idx + 1,
  37.             start_idx + side_len_board - 1,
  38.             start_idx + side_len_board,
  39.             start_idx + side_len_board + 1)
  40.  
  41. def depth_first_search(board_string, side_len_board ,word, start_idx):
  42.     char_to_check = word[0]
  43.     adjacent_indices = get_adjacent_indices(start_idx, side_len_board)
  44.  
  45.     # if we are at the edge of the board we need to remove some "adjanced" indicies
  46.     new_list = []
  47.     # left edge:
  48.     if start_idx % side_len_board == 0:
  49.         for i in range(len(adjacent_indices)):
  50.             if i not in (0, 3, 5):
  51.                 new_list.append(adjacent_indices[i])
  52.     # right edge:
  53.     elif start_idx % side_len_board == side_len_board-1:
  54.         for i in range(len(adjacent_indices)):
  55.             if i not in (2, 4, 7):
  56.                 new_list.append(adjacent_indices[i])
  57.     if new_list:
  58.         adjacent_indices = new_list
  59.  
  60.     # get all characters in adj indices
  61.     chars_in_adj_indices = [board_string[i] for i in adjacent_indices]
  62.     # check if looked for char is in adj. chars > there can be more than 1 match
  63.     match_indices = [adjacent_indices[m.start()] for m in re.finditer(char_to_check, ''.join(chars_in_adj_indices))]
  64.  
  65.     # if there is no match at all, then this can be aborted.
  66.     if not match_indices:
  67.         return False
  68.  
  69.     # mask last char so we don't find it again
  70.     l = (list(board_string))
  71.     l[start_idx] = '0'
  72.     board_new = ''.join(l)
  73.  
  74.     # this set will store the DFS results at all steps
  75.     res_set = []
  76.     if len(word) > 1:
  77.         # as long as any word is left, we recursively call the DFS
  78.         # we store those DFS iterations results in the result set to not abort before we reach a valid branch
  79.         for idx in match_indices:
  80.             res_set.append( depth_first_search(board_new, side_len_board, word[1:], idx) )
  81.  
  82.         # if the result set contains any True value that means one of the branches reached the final True return value
  83.         # and contains a valid branch which reflects the word. In that case we overall can return True
  84.         if any(res_set):
  85.             return True
  86.  
  87.     # if we reached the end of the word and still have matches left, then we have a valid boggle word
  88.     # return this so it will be catched in the res_set of the prior iteration of DFS
  89.     if len(word) == 1:
  90.         return True
  91.  
  92.  
  93.  
  94. test_board = \
  95. [   ["E","A","R","A","V"],
  96.     ["N","L","E","C","D"],
  97.     ["I","A","I","S","T"],
  98.     ["B","Y","O","R","L"],
  99.     ["Z","P","I","E","S"]]
  100.  
  101. testBoard = [
  102.     ["E", "A", "R", "A"],
  103.     ["N", "L", "E", "C"],
  104.     ["I", "A", "I", "S"],
  105.     ["B", "Y", "O", "R"]
  106. ]
  107.  
  108. print(find_word(testBoard, "ALIBZ"))
Advertisement
Add Comment
Please, Sign In to add comment