Search code examples
pythonalgorithmtimebacktrackingsudoku

Is there a way to measure the time taken this algorithm takes to solve this Soduku Puzzle?


I have code to solve a sudoku puzzle using the Backtracking algorithm. I want to find out how long the Backtracking algorithm takes to solve the sudoku puzzle in seconds or milliseceonds using the python language.

My code is '''

from tabulate import tabulate
import timeit

# A 9x9 matrix which represents our sudoku solver
sudoku_board = [
    [0,0,0,0,0,0,2,0,0],
    [0,8,0,0,0,7,0,9,0],
    [6,0,2,0,0,0,5,0,0],
    [0,7,0,0,6,0,0,0,0],
    [0,0,0,9,0,1,0,0,0],
    [0,0,0,0,2,0,0,4,0],
    [0,0,5,0,0,0,6,0,3],
    [0,9,0,4,0,0,0,7,0],
    [0,0,6,0,0,0,0,0,0]
]

# Display the board
def display_board(sudoku_board):
    print(tabulate(sudoku_board, tablefmt='fancy_grid'))


#Look for an unassigned cell if it exists return row and col values else return False
def empty_cells_exist():
    for i in range(9):
        for j in range(9):
            if sudoku_board[i][j] == 0:
                return [i, j]
    return False

# Is our choice good or not?
def valid_number_check(num, i, j):
    #Checking vertically
    for row in range(9):
        if sudoku_board[row][j] == num:
            return False

#Checking horizontally
for col in range(9):
    if sudoku_board[i][col] == num:
        return False

#Check in the 3x3 gird / box
grid_row = (i // 3) * 3
grid_col = (j // 3) * 3

for i in range(3):
    for j in range(3):
        if sudoku_board[grid_row + i][grid_col + j] == num:
            return False

# Once all tests are passed return true
return True

# Solver
def solver():
    cells_exist = empty_cells_exist()

if not cells_exist:
    return True

i, j = cells_exist[0], cells_exist[1]
for num in range(1,10):
    if valid_number_check(num, i, j):
        sudoku_board[i][j] = num
       
        #Backtracking (checking the next step)
        if solver():
            return True
        else:
            sudoku_board[i][j] = 0
            
#     False if nothing (1 through 9) yield an "accepted answer"
    return False



    display_board(sudoku_board)

    if solver():
        display_board(sudoku_board)
    else:
        print("no solution available")

    if __name__ == "__main__":
         print(timeit.timeit(solver,number=10000))

,,,

As you can see I have attempted to time the solver function but it returns a number like 0.07027392299999846 which is not of the format required. I am requiring it to be in a clear readable format for humans to undestand. Such as minutes and seconds format.


Solution

  • For this I usually use datetime.datetime.now:

    >>> import datetime
    >>> begin = datetime.datetime.now()
    >>> begin
    datetime.datetime(2021, 3, 15, ..., 40, 14, 560666)
    >>> end = datetime.datetime.now()
    >>> end - begin
    datetime.timedelta(seconds=10, microseconds=530067)
    >>> str(_)
    '0:00:10.530067' # the nice representation
    

    Or construct the timedelta object yourself:

    >>> datetime.timedelta(seconds=0.07027392299999846)
    datetime.timedelta(microseconds=70274)
    >>> str(_)
    '0:00:00.070274'
    

    So your code could look like this:

    dt = timeit.timeit(solver,number=10000)
    print(datetime.timedelta(seconds=dt))