2
def solveSudoku(self, board: List[List[str]]) -> None:4
Do not return anything, modify board in-place instead.6
full = set("123456789")7
# lets keep rows, columns and boxes sets in hashmaps8
rows = [set() for _ in range(9)]9
cols = [set() for _ in range(9)]10
boxes = [[set() for _ in range(3)] for _ in range(3)]11
# and remember empty cell to fill them in16
if board[i][j] == ".":19
rows[i].add(board[i][j])20
cols[j].add(board[i][j])21
boxes[i // 3][j // 3].add(board[i][j])24
"""returns possible options for i,j intersecting options from row, col and box"""25
return (full - rows[i]) & (full - cols[j]) & (full - boxes[i // 3][j // 3])27
psingle = True # did we have single option decisions in previos traverse29
single = False # for single option decisions in this traverse31
for i, j in deepcopy(empty):34
# we've made a wrong assumption - sudoku is unsolvable37
len(opts) == 2 and not psingle38
): # we have no single-option decisions so have to take an assumption39
board1 = deepcopy(board)40
board1[i][j] = opts.pop()41
board1, empty1 = self.solveSudoku(board1)42
if board1 != None: # if solved - we're done44
for i, b1 in enumerate(board1):46
b1 # have to modify initial list, not just replace the reference49
if len(opts) == 1: # hey, we have a predetermined choice. nice51
board[i][j] = opts.pop()53
rows[i].add(board[i][j])54
cols[j].add(board[i][j])55
boxes[i // 3][j // 3].add(board[i][j])