sudoku validation, sudo solver, basic sub-grid iteration recipe
  1. Problems:
    https://leetcode.com/problems/valid-sudoku/
    https://leetcode.com/problems/sudoku-solver/

  2. Validate a sudoku puzzle. Here given puzzle might not be valid and unsolved.
    Need to just make sure that it is a valid puzzle.

    Entire poblem is just invested in :{validate each row, validate each column and validate each grid}

    Finding individual grid to validate can be tricky for beginners

	'''
        given any index i, j in the 9x9 board 
           this function will baseline itself to
           grid base left and upper most index
           and do the 3x3 grid validation.
    '''
        def gridvalidator(i, j,board):
            
            k = i//3  #gives the base row
            l = j//3  #gives the base column
                      #now grid boundary exist between x:{k*3+[0,3)} y:{l*3+[0,3)}
            cache=defaultdict(lambda:False)
            for m in range(0,3):
                for n in range(0,3):
                    if board[k*3+m][l*3+n] != ".":
                        if cache[board[k*3+m][l*3+n]]:
                            return False
                        cache[board[k*3+m][l*3+n]] = True
            return True

Full solution is here:

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        '''
        1. given any index i, j in the 9x9 board 
           this function will baselines itself to
           grid base left and upper most index
           and do the 3x3 grid validation.
        '''
        def gridvalidator(i, j,board):
            
            k = i//3  #gives the base row
            l = j//3  #gives the base column
                      #now grid boundary exist between x:[k*3+[0,3)] y:[l*3+[0,3)]
            cache=defaultdict(lambda:False)
            for m in range(0,3):
                for n in range(0,3):
                    if board[k*3+m][l*3+n] != ".":
                        if cache[board[k*3+m][l*3+n]]:
                            return False
                        cache[board[k*3+m][l*3+n]] = True
            return True
        
        def columnvalidator(j, board):
            cache=defaultdict(lambda:False)
            for i in range(9):
                if board[i][j] != ".":
                    if cache[board[i][j]]:
                        return False
                    cache[board[i][j]] = True
            return True
        
        def rowvalidator(i, board):
            cache=defaultdict(lambda:False)
            for j in range(9):
                if board[i][j] != ".":                
                    if cache[board[i][j]]:
                        return False
                    cache[board[i][j]] = True
            return True
        
        #pass only the grid base index
        i = 0
        while i < 9:
            j=0
            while j < 9:
                if gridvalidator(i,j,board) == False:
                    return False
                j+=3
            i+=3
            
        #pass each column index
        j = 0
        while j < 9:
            if columnvalidator(j, board) == False:
                return False
            j+=1
        
        i = 0
        while i < 9:
            if rowvalidator(i, board) == False:
                return False
            i+=1
        return True
  1. Sudoku solver: Given a valid sudoku solve the puzzle
    Unlike validator here backtracking is needed.
    Reuse the recipies of colum, row and grid but this time to generate candidates for
    filling the puzzle.

            def columncandidates(j,s,board):
            for i in range(9):
                if board[i][j] != "." and board[i][j] in s:
                    s.remove(str(board[i][j]))
            return True
    
        def rowcandidates(i,s,board):
            for j in range(9):
                if board[i][j] != "." and board[i][j] in s:
                    s.remove(str(board[i][j]))
            return True        
        
        def gridcandidates(i,j,s,board):
            k = i//3  #gives the base row
            l = j//3  #gives the base column
                      #now grid boundary exist between x:[k*3+[0,3)] y:[l*3+[0,3)]
            for m in range(0,3):
                for n in range(0,3):
                    if board[k*3+m][l*3+n] != "." and board[k*3+m][l*3+n] in s:
                        s.remove(board[k*3+m][l*3+n])
            return True

    Full solution:

    class Solution:
    def solveSudoku(self, board: List[List[str]]) -> None:
        """
        Do not return anything, modify board in-place instead.
        """
    
        def columncandidates(j,s,board):
            for i in range(9):
                if board[i][j] != "." and board[i][j] in s:
                    s.remove(str(board[i][j]))
            return True
    
        def rowcandidates(i,s,board):
            for j in range(9):
                if board[i][j] != "." and board[i][j] in s:
                    s.remove(str(board[i][j]))
            return True        
        
        def gridcandidates(i,j,s,board):
            k = i//3  #gives the base row
            l = j//3  #gives the base column
                      #now grid boundary exist between x:[k*3+[0,3)] y:[l*3+[0,3)]
            for m in range(0,3):
                for n in range(0,3):
                    if board[k*3+m][l*3+n] != "." and board[k*3+m][l*3+n] in s:
                        s.remove(board[k*3+m][l*3+n])
            return True
        
        def dfs(i,j,board):
            if i == 9:
                return True
            
            while board[i][j] != ".":
                if j == 8:
                    i+=1
                    j=0
                else:
                    j+=1
                if i > 8:
                    return True
                
            
            s=set([str(_) for _ in range(1,10)])
            columncandidates(j,s,board)
            rowcandidates(i,s,board)
            gridcandidates(i,j,s,board)
            for cand in s:
                board[i][j] = cand
                if j == 8:
                    row = i+1
                    col = 0
                else:
                    row = i
                    col = j+1
                if dfs(row, col,board) == True:
                    return True    
            board[i][j] = "."
            return False
        
        dfs(0,0,board)
        return board
        
Comments (0)