Algorithm for solving Sudoku

后端 未结 10 588
忘了有多久
忘了有多久 2020-12-02 08:13

I want to write a code in python to solve a sudoku puzzle. Do you guys have any idea about a good algorithm for this purpose. I read somewhere in net about a algorithm which

10条回答
  •  孤城傲影
    2020-12-02 08:56

    I know I'm late, but this is my version:

    board = [
        [8, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 3, 6, 0, 0, 0, 0, 0],
        [0, 7, 0, 0, 9, 0, 2, 0, 0],
        [0, 5, 0, 0, 0, 7, 0, 0, 0],
        [0, 0, 0, 0, 4, 5, 7, 0, 0],
        [0, 0, 0, 1, 0, 0, 0, 3, 0],
        [0, 0, 1, 0, 0, 0, 0, 6, 8],
        [0, 0, 8, 5, 0, 0, 0, 1, 0],
        [0, 9, 0, 0, 0, 0, 4, 0, 0]
    ]
    
    
    def solve(bo):
        find = find_empty(bo)
        if not find:  # if find is None or False
            return True
        else:
            row, col = find
    
        for num in range(1, 10):
            if valid(bo, num, (row, col)):
                bo[row][col] = num
    
                if solve(bo):
                    return True
    
                bo[row][col] = 0
    
        return False
    
    
    def valid(bo, num, pos):
    
        # Check row
        for i in range(len(bo[0])):
            if bo[pos[0]][i] == num and pos[1] != i:
                return False
    
        # Check column
        for i in range(len(bo)):
            if bo[i][pos[1]] == num and pos[0] != i:
                return False
    
        # Check box
        box_x = pos[1] // 3
        box_y = pos[0] // 3
    
        for i in range(box_y*3, box_y*3 + 3):
            for j in range(box_x*3, box_x*3 + 3):
                if bo[i][j] == num and (i, j) != pos:
                    return False
    
        return True
    
    
    def print_board(bo):
        for i in range(len(bo)):
            if i % 3 == 0:
                if i == 0:
                    print(" ┎─────────┰─────────┰─────────┒")
                else:
                    print(" ┠─────────╂─────────╂─────────┨")
    
            for j in range(len(bo[0])):
                if j % 3 == 0:
                    print(" ┃ ", end=" ")
    
                if j == 8:
                    print(bo[i][j], " ┃")
                else:
                    print(bo[i][j], end=" ")
    
        print(" ┖─────────┸─────────┸─────────┚")
    
    
    def find_empty(bo):
        for i in range(len(bo)):
            for j in range(len(bo[0])):
                if bo[i][j] == 0:
                    return i, j  # row, column
    
        return None
    
    
    print_board(board)
    print('\n--------------------------------------\n')
    solve(board)
    print_board(board)
    

    It uses backtracking. But is not coded by me, it's Tech With Tim's. That list contains the world hardest sudoku, and by implementing the timing function, the time is:

    ===========================
    [Finished in 2.838 seconds]
    ===========================
    

    But with a simple sudoku puzzle like:

    board = [
        [7, 8, 0, 4, 0, 0, 1, 2, 0],
        [6, 0, 0, 0, 7, 5, 0, 0, 9],
        [0, 0, 0, 6, 0, 1, 0, 7, 8],
        [0, 0, 7, 0, 4, 0, 2, 6, 0],
        [0, 0, 1, 0, 5, 0, 9, 3, 0],
        [9, 0, 4, 0, 6, 0, 0, 0, 5],
        [0, 7, 0, 3, 0, 0, 0, 1, 2],
        [1, 2, 0, 0, 0, 7, 4, 0, 0],
        [0, 4, 9, 2, 0, 6, 0, 0, 7]
    ]
    

    The result is :

    ===========================
    [Finished in 0.011 seconds]
    ===========================
    

    Pretty fast I can say.

提交回复
热议问题