Data Structures and Algorithm
Data Structures and Algorithm
1
Objective:
The aim of our project is to apply the concepts and learning outcomes of the Data Structures and Algorithms
(DSA) course in an engaging and practical manner. This project focuses on developing a comprehensive
Sudoku generator and solver, which provides the user with puzzles of varying difficulties, selected according
to their preferences. This not only fosters continuous engagement in problem-solving but also enhances
logical and analytical skills through a hands-on approach. It underscores the relevance of DSA principles in
developing effective and efficient solutions to complex problems, thereby enhancing the educational value
of the course. Therefore, it provides a robust framework for us to sharpen our computational thinking in a
fun and interactive method.
2
Block Diagram:
Main Menu
Provides options to generate a
Sudoku, solve a puzzle, or exit.
Generate Sudoku
Creates a 9 x 9 Sudoku board
based on difficulty entered
Input a Sudoku
Allows the user to enter a
Sudoku puzzle manually.
Solve Sudoku
Solves & displays the sudoku
puzzle
Exit
Exits the program.
3
Block Diagram Explanation:
1. Main Menu
- The program starts with the `main()` function, which continuously displays a menu with three options:
1. Generate a new Sudoku puzzle.
2. Solve a Sudoku puzzle (either generated or entered by the user).
3. Exit the program.
- Based on the user’s choice, the program calls the appropriate function to generate or solve a puzzle or to
exit.
2. Generate Sudoku
- If the user selects to generate a Sudoku puzzle, they are asked to choose a difficulty level (easy, medium,
or hard). Each level corresponds to a certain number of empty cells:
- Easy (fewer empty cells)
- Medium
- Hard (more empty cells)
- The `generate_sudoku(difficulty)` function creates the puzzle:
- Shuffles Rows and Columns: It shuffles rows, columns, and numbers to generate a randomized, valid
Sudoku board.
- Patterns: Uses a pattern to ensure that the generated board follows Sudoku rules.
- Remove Numbers: Randomly removes numbers from cells according to the difficulty level to create a
puzzle with varying challenges.
- The generated puzzle is displayed using the `print_board()` function, where:
- Chosen Numbers are displayed in their cells, and empty positions are shown as "X".
- The `print_board()` function organizes the display with lines separating 3x3 blocks for easy readability.
4. Solve Sudoku
- If the user chooses to solve a puzzle (either generated or entered), the `solve_sudoku()` function is called:
4
- Backtracking Algorithm: The function uses a recursive backtracking algorithm to try each possible
number in each empty cell until it finds a solution.
- Validity Check: The `is_possible()` helper function checks if a number can be placed in a specific cell
without violating Sudoku rules (no repeats in the same row, column, or 3x3 box).
- Solution Display: If the puzzle is solvable, the function displays the completed Sudoku grid. If the
puzzle is unsolvable, it displays an appropriate message.
5. Exit Program
- If the user selects the exit option, the program stops running and displays a goodbye message.
5
Code:
import numpy as np
import random
def print_board(board):
for i, row in enumerate(board):
if i % 3 == 0 and i != 0:
print("- " * 11)
for j, num in enumerate(row):
if j % 3 == 0 and j != 0:
print("| ", end="")
if num == 0:
print("X ", end="")
else:
print(f"{num} ", end="")
print()
def generate_sudoku(difficulty):
base = 3
side = base * base
r_base = range(base)
rows = [g * base + r for g in shuffle(r_base) for r in shuffle(r_base)]
cols = [g * base + c for g in shuffle(r_base) for c in shuffle(r_base)]
nums = shuffle(range(1, base * base + 1))
return board
def solve_sudoku(board):
def is_possible(board, y, x, n):
for i in range(9):
if board[y][i] == n or board[i][x] == n:
return False
x0, y0 = (x // 3) * 3, (y // 3) * 3
for i in range(3):
for j in range(3):
if board[y0 + i][x0 + j] == n:
return False
return True
for y in range(9):
6
for x in range(9):
if board[y][x] == 0:
for n in range(1, 10):
if is_possible(board, y, x, n):
board[y][x] = n
if solve_sudoku(board):
return True
board[y][x] = 0
return False
return True
def main():
generated_board = None
while True:
print("\n============================")
print(" Sudoku Menu ")
print("============================")
print("1. Generate Sudoku")
print("2. Solve Sudoku")
print("3. Exit")
print("============================")
choice = input("Enter your choice: ")
if choice == "1":
print("\n============================")
print(" Select Difficulty ")
print("============================")
print("1. Easy")
print("2. Medium")
print("3. Hard")
print("============================")
difficulty_choice = input("Enter your choice: ")
if difficulty_choice == "1":
difficulty = 4
elif difficulty_choice == "2":
difficulty = 6
elif difficulty_choice == "3":
difficulty = 8
else:
print("Invalid choice. Please select a valid difficulty.")
continue
generated_board = generate_sudoku(difficulty)
print("\nGenerated Sudoku:")
print_board(generated_board)
7
solve_choice = input("Enter your choice: ")
if solve_choice == "1":
board = generated_board
elif solve_choice == "2":
board = []
print("Enter the Sudoku to solve (use 'X' or 'x' for empty spaces):")
for _ in range(9):
row = input().strip().split()
board.append([int(num) if num.upper() != 'X' else 0 for num in row])
else:
print("Invalid choice. Please select a valid option.")
continue
else:
board = []
print("Enter the Sudoku to solve (use 'X' or 'x' for empty spaces):")
for _ in range(9):
row = input().strip().split()
board.append([int(num) if num.upper() != 'X' else 0 for num in row])
print("Solving Sudoku...")
if solve_sudoku(board):
print("\nSolved Sudoku:")
print_board(board)
else:
print("No solution exists!")
else:
print("Invalid choice. Please enter 1, 2, or 3.")
if __name__ == "__main__":
main()