Python | Multiple Sudoku Solver

Python | Multiple Sudoku Solver

By Casper_x | Python Programs | 15 Mar 2023


Python Sudoku Solver: Solving 50 Sudokus in Record Time.

 

d557736f35dc5e08c44f87d82dfdd5e1a09e5ef3374bfda577227fff056e572a.png

 

Are you a fan of Sudoku? Discover how a computer program solves 50 Sudoku puzzles in record time!

Sudoku is one of the most popular puzzle games in the world, with grids that can sometimes seem impossible to solve. Fortunately, with the power of Python, it is possible to solve Sudoku grids in no time.

If you are looking to solve Sudoku grids, these 2 codes might interest you.

Today, we will see together how to solve multiple Sudoku grids in a row, using the Sudoku Solver  code as our base.

 

What is ‘Time’

 

The 'time' library provides access to several time-related functions in Python.

I invite you to check out my post on Time Library for more information.

 

Prerequisites

 

First of all, you need a file named 'sudoku_grid.txt' that contains the different Sudoku grids in this format:

You can paste or download 'sudoku.txt' on this website which contains various grid of Sudoku.

 

fb2fa9869f72ca55b09595a2b0c0bf4813d06e8d29ff0c82292d4afadfaebd6d.png

 

And, you need to import ‘time’ module.

 

import time

Program

 

As previously seen in my Sudoku Solver post, my code is a basic implementation of the Sudoku solver, which solves a pre-defined grid using a recursive 'solve_sudoku()' function.

 

def solve_sudoku(grid):

    empty_cell = find_empty_cell(grid)

    if not empty_cell:

        return True

    row, col = empty_cell

    for num in range(1, 10):

        if is_valid(grid, row, col, num):

            grid[row][col] = num

            if solve_sudoku(grid):

                return True

            grid[row][col] = 0

    return False

 

The function 'find_empty_cell()' is used to find the next empty cell to fill, and 'is_valid()' is used to check if a value can be placed in a specific cell without breaking the rules of Sudoku.

 

find_empty_cell()

 

def find_empty_cell(grid):

    for row in range(9):

        for col in range(9):

            if grid[row][col] == 0:

                return row, col

    return None

 

is_valid() :

 

def is_valid(grid, row, col, num):

    for i in range(9):

        if grid[row][i] == num or grid[i][col] == num:

            return False

    row_start = (row // 3) * 3

    col_start = (col // 3) * 3

    for i in range(row_start, row_start + 3):

        for j in range(col_start, col_start + 3):

            if grid[i][j] == num:

                return False

    return True

 

This code provides a good foundation for understanding the basic algorithms for solving Sudoku puzzles. I will not go into further detail on these parts, and I encourage you to refer to the Sudoku Solver post for more information.

Based on this, we will add the ability to solve multiple sudokus from a text file, which will allow us to measure the average time taken to solve a sudoku. We will also use the ‘time’ function to measure the time taken to solve each sudoku and the total time taken to solve all the sudokus. In comparison to the first code that solves only one sudoku using a pre-defined grid, our new code is more efficient in solving a large number of sudokus and measuring the performance of the sudoku solver.

 

Alright, to start off we will initialize a timer with 'total_start_time = time.time()' to record the total time taken to solve the 50 sudokus.

 

# Start the timer for all 50 sudokus

total_start_time = time.time() 

 

Next, the second part of the code opens the file 'sudoku_grid.txt' in read mode (with open('sudoku_grid.txt', 'r') as f:) and reads its content. The grids are stored as strings separated by double line breaks ('\n\n').

The 'strip()' method removes spaces at the beginning and end of the string. The 'split()' method with ('\n\n') as an argument divides the string into a list of strings corresponding to each sudoku grid.

The variable 'grids' thus contains a list of strings representing each sudoku grid.

 

# Read in the sudoku grids from the file

with open(‘sudoku_grid.txt’, ‘r') as f:

    grids = f.read().strip().split(‘\n\n’)

 

The variable 'total_solve_time' is initialized to 0 to record the total time needed to solve the 50 sudokus.

 

total_solve_time = 0  # Initialize the total time taken to solve all 50 sudokus

 

The third part of the code solves each sudoku grid stored in the variable 'grids'. The 'for' loop with the 'enumerate()' method iterates through the grids, and each grid is stored in the variable 'grid_str'.

The 'enumerate()' method returns a tuple containing the index and current element of the loop, which allows displaying the number of each solved sudoku grid with '"Solving Sudoku #{}…".format(i+1)'.

The variable 'grid' is initialized with a list comprehension that converts each character of the string 'grid_str' into an integer with 'int(c)', to create a two-dimensional list representing the sudoku grid.

 

# Solve each sudoku grid and print the result

for i, grid_str in enumerate(grids):

    print(‘Solving Sudoku #{}…'.format(i+1)) # Optionnal

    grid = [[int(c) for c in row] for row in grid_str.split(‘\n')]

 

The timer to solve each Sudoku grid is initialized with 'start_time = time.time()'. 

The 'solve_sudoku()' function is called to solve each Sudoku grid. If the function returns True, it means that the grid has been successfully solved, and the time taken to solve this grid is recorded with 'solve_time = time.time() - start_time'. 

This time is added to the total time with 'total_solve_time += solve_time'.

Then, the code displays a message indicating that the Sudoku grid has been successfully solved and the time taken to solve it, using Python's 'print()' method.

 

start_time = time.time()  # Start the timer for this sudoku

if solve_sudoku(grid):

    solve_time = time.time() - start_time  # Calculate the time taken to solve this sudoku

    total_solve_time += solve_time

print('Solved Sudoku #{} in {:.4f} seconds:'.format(i+1, solve_time))

 

Within a 'for' loop, we will ensure to display the solved sudoku grids.

 

for row in grid:

    print(‘ ‘.join(str(c) for c in row))

 

If the function 'solve_sudoku()' returns False, it means that the grid could not be solved and the message 'Unable to solve Sudoku #{}.' is displayed with '"Unable to solve Sudoku #{}.".format(i+1)'.

 

else:

    print(‘Unable to solve Sudoku #{}.’.format(I+1))

 

Well, the last part of the code calls the ‘print()’ function to display the solved sudoku grids.

 

print()

 

The last lines of code measure the total time taken to solve the 50 sudokus using Python's time function. 

The first line calculates the total time taken to solve the 50 sudokus.

 

 # Calculate the total time taken to solve all 50 sudokus

total_time = time.time() - total_start_time

 

That second line displays the total time taken to solve all 50 sudokus with a precision of 4 decimal places.

 

print('Solved all 50 sudokus in {:.4f} seconds.'.format(total_time))

 

The third line displays the average time taken to solve each sudoku by using the formula ‘total_solve_time / len(grids)’.

 

print('Average solve time per sudoku: {:.4f} seconds.'.format(total_solve_time / len(grids)))

 

Comparing the total and average solve times can help evaluate the efficiency of different algorithm implementations for solving Sudoku puzzles.

 

Your added code to the base code (Sudoku Solver) today should look like this :

 

total_start_time = time.time()  # Start the timer for all 50 sudokus

# Read in the sudoku grids from the file

with open(‘sudoku_grid.txt', ‘r') as f:

    grids = f.read().strip().split(‘\n\n’)

total_solve_time = 0  # Initialize the total time taken to solve all 50 sudokus

# Solve each sudoku grid and print the result

for i, grid_str in enumerate(grids):

    print(‘Solving Sudoku #{}…'.format(i+1)) # Optionnal

    grid = [[int(c) for c in row] for row in grid_str.split(‘\n’)]

    start_time = time.time()  # Start the timer for this sudoku

    if solve_sudoku(grid):

        solve_time = time.time() - start_time  # Calculate the time taken to solve this sudoku

        total_solve_time += solve_time

        print(‘Solved Sudoku #{} in {:.4f} seconds:'.format(i+1, solve_time))

        for row in grid:

            print(‘ ‘.join(str(c) for c in row))

    else:

        print(‘Unable to solve Sudoku #{}.’.format(I+1))

    print()

total_time = time.time() - total_start_time  # Calculate the total time taken to solve all 50 sudokus

print(‘Solved all 50 sudokus in {:.4f} seconds.’.format(total_time))

print(‘Average solve time per sudoku: {:.4f} seconds.’.format(total_solve_time / len(grids)))

In the end, our sudoku solver program is an excellent example of using simple yet powerful algorithms to solve complex problems. We have developed an efficient solution for solving a single sudoku grid, as well as a method for solving multiple sudokus from a text file. By using the time function to measure the time taken to solve each sudoku and the total time taken to solve all the sudokus, we have provided accurate results on the performance of our program.

 

9e437d99d9cf7d0467a35824e776784d6a880e3eaad83eaffa97150f6672029b.png

 

As always, the complete code is at the end of the publication.

Thank you and congratulations to all those who didn't give up on reading this post.

Leave a comment if you have any questions

 

If you enjoy my blog posts, you can support me.

Thanks for you support 🙏

 

BTC : bc1qvfmetg2d36mmntrg56ld0tdrte8cqeygjxdpsg

ETH  | USDC | USDT : 0x02AbfBf22fA72d068Ff305e58dF782e58F863274

EGLD : erd1jc0lms8zl64nwsy3srm0q2pllvvppkgcsa6eyaketxetcs6fpl7q0cty6a

DOGE : DLtGbPrFvwW5y7jFuvuDAkZGNB2eAErAxA

 

See you soon ! 🤙

Casper_X 👻

 

Want More Program ?

 

Take a look of these posts.

Scrabble Helper : https://www.publish0x.com/python-scrabble-helper/python-scrabble-helper-xvmqykg

QRcode generator : https://www.publish0x.com/python-scrabble-helper/python-qr-code-generator-xrgmxnx

Face detection : https://www.publish0x.com/python-scrabble-helper/python-face-detection-xjrwygy

Password generator : https://www.publish0x.com/python-scrabble-helper/python-password-generator-xyezmel

Caesar Cipher : https://www.publish0x.com/python-scrabble-helper/python-caesar-cipher-xvmqnex

Tkinter Scrabble Helper : https://www.publish0x.com/python-scrabble-helper/python-scrabble-helper-tkinter-xqelzgv

Sudoku Solver : https://www.publish0x.com/python-scrabble-helper/python-sudoku-solver-xkpwwvq

Decrypt Caesar : https://www.publish0x.com/python-scrabble-helper/python-decrypt-caesar-encryption-xwydpzo

 

Want Learn More About 'Python' ?

 

Take a look of these posts.

Python programms : https://www.publish0x.com/python-scrabble-helper

Python module : https://www.publish0x.com/python-modules

 

Here is the full program :

 

import time

def solve_sudoku(grid):
    empty_cell = find_empty_cell(grid)
    if not empty_cell:
        return True

    row, col = empty_cell

    for num in range(1, 10):
        if is_valid(grid, row, col, num):
            grid[row][col] = num
            if solve_sudoku(grid):
                return True
            grid[row][col] = 0

    return False


def find_empty_cell(grid):
    for row in range(9):
        for col in range(9):
            if grid[row][col] == 0:
                return row, col
    return None


def is_valid(grid, row, col, num):
    for i in range(9):
        if grid[row][i] == num or grid[i][col] == num:
            return False

    row_start = (row // 3) * 3
    col_start = (col // 3) * 3

    for i in range(row_start, row_start + 3):
        for j in range(col_start, col_start + 3):
            if grid[i][j] == num:
                return False

    return True

total_start_time = time.time()  # Start the timer for all 50 sudokus

# Read in the sudoku grids from the file
with open('sudoku_grid.txt', 'r') as f:
    grids = f.read().strip().split('\n\n')

total_solve_time = 0  # Initialize the total time taken to solve all 50 sudokus

# Solve each sudoku grid and print the result
for i, grid_str in enumerate(grids):
    print('Solving Sudoku #{}...'.format(i+1)) # Optionnal
    grid = [[int(c) for c in row] for row in grid_str.split('\n')]
    start_time = time.time()  # Start the timer for this sudoku
    if solve_sudoku(grid):
        solve_time = time.time() - start_time  # Calculate the time taken to solve this sudoku
        total_solve_time += solve_time
        print('Solved Sudoku #{} in {:.4f} seconds:'.format(i+1, solve_time))
        for row in grid:
            print(' '.join(str(c) for c in row))
    else:
        print('Unable to solve Sudoku #{}.'.format(i+1))
    print()

total_time = time.time() - total_start_time  # Calculate the total time taken to solve all 50 sudokus

print('Solved all 50 sudokus in {:.4f} seconds.'.format(total_time))
print('Average solve time per sudoku: {:.4f} seconds.'.format(total_solve_time / len(grids)))





How do you rate this article?

5


Casper_x
Casper_x

Python | Crypto | Javascript | Programming


Python Programs
Python Programs

Tutorials on the programming language 'Python'. In this blog you will find several basics Python programs to complete. Hope you enjoy the content !

Publish0x

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.