def is_drivable(start, finish, grid): R = len(grid) C = len(grid[0]) directions = [(0, -1), (0, 1), (-1, 0), (1, 0)] # West, East, North, South # Function to check if a cell is valid and not a wall or hazard def is_valid(r, c): return r >= 0 and r < R and c >= 0 and c < C and grid[r][c] != '#' and grid[r][c] != '*' # Function to simulate car movement def move(r, c, dr, dc): r += dr c += dc if is_valid(r, c): return r, c return None # Function to recursively explore all possible paths from start to finish def explore(r, c, visited): if (r, c) == finish: return True visited.add((r, c)) for dr, dc in directions: new_r, new_c = move(r, c, dr, dc) if new_r is not None and (new_r, new_c) not in visited: if explore(new_r, new_c, visited): return True return False # Check if start and finish are drivable visited = set() if explore(start[0], start[1], visited): return True else: return False def find_drivable_pairs(T, test_cases): results = [] for t in range(T): R, C = test_cases[t][0] grid = test_cases[t][1] starts = [] finishes = [] drivable_pairs = [] # Find all interesting starts and finishes for r in range(R): for c in range(C): if grid[r][c].islower(): starts.append((r, c)) elif grid[r][c].isupper(): finishes.append((r, c)) # Check all combinations of starts and finishes for start in starts: for finish in finishes: if is_drivable(start, finish, grid): drivable_pairs.append(grid[start[0]][start[1]].lower() + grid[finish[0]][finish[1]].lower()) # Sort the drivable pairs alphabetically drivable_pairs.sort() # Append the results for this test case if len(drivable_pairs) > 0: results.append("Case #{}: {}".format(t + 1, ' '.join(drivable_pairs))) else: results.append("Case #{}: NONE".format(t + 1)) return results # Example usage T = 4 test_cases = [((1, 2), ['aZ']), ((4, 4), ['a..c', '**.*', '.Y.#', 'bX#Z']), ((2, 2), ['a*', '*Z']), ((2, 7), ['a*bcd*.', '...*F#.'])] results = find_drivable_pairs(T, test_cases) for result in results: print(result)