Program for Sudoku Generator
Background:
Following are the rules of Sudoku for a player.
- In all 9 sub matrices 3×3 the elements should be 1-9, without repetition.
- In all rows there should be elements between 1-9 , without repetition.
- In all columns there should be elements between 1-9 , without repetition.
The task is to generate a 9 x 9 Sudoku grid that is valid, i.e., a player can fill the grid following above set of rules.
A simple naïve solution can be.
- Randomly take any number 1-9.
- Check if it is safe to put in the cell.(row , column and box)
- If safe, place it and increment to next location and go to step 1.
- If not safe, then without incrementing go to step 1.
- Once matrix is fully filled, remove k no. of elements randomly to complete game.
Improved Solution : We can improve the solution, if we understand a pattern in this game. We can observe that all 3 x 3 matrices, which are diagonally present are independent of other 3 x 3 adjacent matrices initially, as others are empty.
3 8 5 0 0 0 0 0 0 9 2 1 0 0 0 0 0 0 6 4 7 0 0 0 0 0 0 0 0 0 1 2 3 0 0 0 0 0 0 7 8 4 0 0 0 0 0 0 6 9 5 0 0 0 0 0 0 0 0 0 8 7 3 0 0 0 0 0 0 9 6 2 0 0 0 0 0 0 1 4 5
(We can observe that in above matrix, the diagonal matrices are independent of other empty matrices initially). So if we fill them first, then we will only have to do box check and thus column/row check not required.
Secondly, while we fill rest of the non-diagonal elements, we will not have to use random generator, but we can fill recursively by checking 1 to 9.
Following is the improved logic for the problem. 1. Fill all the diagonal 3x3 matrices. 2. Fill recursively rest of the non-diagonal matrices. For every cell to be filled, we try all numbers until we find a safe number to be placed. 3. Once matrix is fully filled, remove K elements randomly to complete game.
C++
/* C++ program for Sudoku generator */ #include <bits/stdc++.h> using namespace std; class Sudoku { public : int ** mat; int N; // number of columns/rows. int SRN; // square root of N int K; // No. Of missing digits // Constructor Sudoku( int N, int K) { this ->N = N; this ->K = K; // Compute square root of N double SRNd = sqrt (N); SRN = ( int )SRNd; mat = new int *[N]; // Create a row for every pointer for ( int i = 0; i < N; i++) { // Note : Rows may not be contiguous mat[i] = new int [N]; // Initialize all entries as false to indicate // that there are no edges initially memset (mat[i], 0, N * sizeof ( int )); } } // Sudoku Generator void fillValues() { // Fill the diagonal of SRN x SRN matrices fillDiagonal(); // Fill remaining blocks fillRemaining(0, SRN); // Remove Randomly K digits to make game removeKDigits(); } // Fill the diagonal SRN number of SRN x SRN matrices void fillDiagonal() { for ( int i = 0; i < N; i = i + SRN) { // for diagonal box, start coordinates->i==j fillBox(i, i); } } // Returns false if given 3 x 3 block contains num. bool unUsedInBox( int rowStart, int colStart, int num) { for ( int i = 0; i < SRN; i++) { for ( int j = 0; j < SRN; j++) { if (mat[rowStart + i][colStart + j] == num) { return false ; } } } return true ; } // Fill a 3 x 3 matrix. void fillBox( int row, int col) { int num; for ( int i = 0; i < SRN; i++) { for ( int j = 0; j < SRN; j++) { do { num = randomGenerator(N); } while (!unUsedInBox(row, col, num)); mat[row + i][col + j] = num; } } } // Random generator int randomGenerator( int num) { return ( int ) floor ( ( float )( rand () / double (RAND_MAX) * num + 1)); } // Check if safe to put in cell bool CheckIfSafe( int i, int j, int num) { return ( unUsedInRow(i, num) && unUsedInCol(j, num) && unUsedInBox(i - i % SRN, j - j % SRN, num)); } // check in the row for existence bool unUsedInRow( int i, int num) { for ( int j = 0; j < N; j++) { if (mat[i][j] == num) { return false ; } } return true ; } // check in the row for existence bool unUsedInCol( int j, int num) { for ( int i = 0; i < N; i++) { if (mat[i][j] == num) { return false ; } } return true ; } // A recursive function to fill remaining // matrix bool fillRemaining( int i, int j) { // System.out.println(i+" "+j); if (j >= N && i < N - 1) { i = i + 1; j = 0; } if (i >= N && j >= N) { return true ; } if (i < SRN) { if (j < SRN) { j = SRN; } } else if (i < N - SRN) { if (j == ( int )(i / SRN) * SRN) { j = j + SRN; } } else { if (j == N - SRN) { i = i + 1; j = 0; if (i >= N) { return true ; } } } for ( int num = 1; num <= N; num++) { if (CheckIfSafe(i, j, num)) { mat[i][j] = num; if (fillRemaining(i, j + 1)) { return true ; } mat[i][j] = 0; } } return false ; } // Remove the K no. of digits to // complete game void removeKDigits() { int count = K; while (count != 0) { int cellId = randomGenerator(N * N) - 1; // System.out.println(cellId); // extract coordinates i and j int i = (cellId / N); int j = cellId % 9; if (j != 0) { j = j - 1; } // System.out.println(i+" "+j); if (mat[i][j] != 0) { count--; mat[i][j] = 0; } } } // Print sudoku void printSudoku() { for ( int i = 0; i < N; i++) { for ( int j = 0; j < N; j++) { cout << to_string(mat[i][j]) + " " ; } cout << endl; } cout << endl; } }; // Driver code int main() { int N = 9; int K = 20; Sudoku* sudoku = new Sudoku(N, K); sudoku->fillValues(); sudoku->printSudoku(); return 0; } // This code is contributed by Aarti_Rathi |
Java
/* Java program for Sudoku generator */ import java.lang.*; public class Sudoku { int [] mat[]; int N; // number of columns/rows. int SRN; // square root of N int K; // No. Of missing digits // Constructor Sudoku( int N, int K) { this .N = N; this .K = K; // Compute square root of N Double SRNd = Math.sqrt(N); SRN = SRNd.intValue(); mat = new int [N][N]; } // Sudoku Generator public void fillValues() { // Fill the diagonal of SRN x SRN matrices fillDiagonal(); // Fill remaining blocks fillRemaining( 0 , SRN); // Remove Randomly K digits to make game removeKDigits(); } // Fill the diagonal SRN number of SRN x SRN matrices void fillDiagonal() { for ( int i = 0 ; i<N; i=i+SRN) // for diagonal box, start coordinates->i==j fillBox(i, i); } // Returns false if given 3 x 3 block contains num. boolean unUsedInBox( int rowStart, int colStart, int num) { for ( int i = 0 ; i<SRN; i++) for ( int j = 0 ; j<SRN; j++) if (mat[rowStart+i][colStart+j]==num) return false ; return true ; } // Fill a 3 x 3 matrix. void fillBox( int row, int col) { int num; for ( int i= 0 ; i<SRN; i++) { for ( int j= 0 ; j<SRN; j++) { do { num = randomGenerator(N); } while (!unUsedInBox(row, col, num)); mat[row+i][col+j] = num; } } } // Random generator int randomGenerator( int num) { return ( int ) Math.floor((Math.random()*num+ 1 )); } // Check if safe to put in cell boolean CheckIfSafe( int i, int j, int num) { return (unUsedInRow(i, num) && unUsedInCol(j, num) && unUsedInBox(i-i%SRN, j-j%SRN, num)); } // check in the row for existence boolean unUsedInRow( int i, int num) { for ( int j = 0 ; j<N; j++) if (mat[i][j] == num) return false ; return true ; } // check in the row for existence boolean unUsedInCol( int j, int num) { for ( int i = 0 ; i<N; i++) if (mat[i][j] == num) return false ; return true ; } // A recursive function to fill remaining // matrix boolean fillRemaining( int i, int j) { // System.out.println(i+" "+j); if (j>=N && i<N- 1 ) { i = i + 1 ; j = 0 ; } if (i>=N && j>=N) return true ; if (i < SRN) { if (j < SRN) j = SRN; } else if (i < N-SRN) { if (j==( int )(i/SRN)*SRN) j = j + SRN; } else { if (j == N-SRN) { i = i + 1 ; j = 0 ; if (i>=N) return true ; } } for ( int num = 1 ; num<=N; num++) { if (CheckIfSafe(i, j, num)) { mat[i][j] = num; if (fillRemaining(i, j+ 1 )) return true ; mat[i][j] = 0 ; } } return false ; } // Remove the K no. of digits to // complete game public void removeKDigits() { int count = K; while (count != 0 ) { int cellId = randomGenerator(N*N)- 1 ; // System.out.println(cellId); // extract coordinates i and j int i = (cellId/N); int j = cellId% 9 ; if (j != 0 ) j = j - 1 ; // System.out.println(i+" "+j); if (mat[i][j] != 0 ) { count--; mat[i][j] = 0 ; } } } // Print sudoku public void printSudoku() { for ( int i = 0 ; i<N; i++) { for ( int j = 0 ; j<N; j++) System.out.print(mat[i][j] + " " ); System.out.println(); } System.out.println(); } // Driver code public static void main(String[] args) { int N = 9 , K = 20 ; Sudoku sudoku = new Sudoku(N, K); sudoku.fillValues(); sudoku.printSudoku(); } } |
Python3
import random import math class Sudoku: def __init__( self , N, K): self .N = N self .K = K # Compute square root of N SRNd = math.sqrt(N) self .SRN = int (SRNd) self .mat = [[ 0 for _ in range (N)] for _ in range (N)] def fillValues( self ): # Fill the diagonal of SRN x SRN matrices self .fillDiagonal() # Fill remaining blocks self .fillRemaining( 0 , self .SRN) # Remove Randomly K digits to make game self .removeKDigits() def fillDiagonal( self ): for i in range ( 0 , self .N, self .SRN): self .fillBox(i, i) def unUsedInBox( self , rowStart, colStart, num): for i in range ( self .SRN): for j in range ( self .SRN): if self .mat[rowStart + i][colStart + j] = = num: return False return True def fillBox( self , row, col): num = 0 for i in range ( self .SRN): for j in range ( self .SRN): while True : num = self .randomGenerator( self .N) if self .unUsedInBox(row, col, num): break self .mat[row + i][col + j] = num def randomGenerator( self , num): return math.floor(random.random() * num + 1 ) def checkIfSafe( self , i, j, num): return ( self .unUsedInRow(i, num) and self .unUsedInCol(j, num) and self .unUsedInBox(i - i % self .SRN, j - j % self .SRN, num)) def unUsedInRow( self , i, num): for j in range ( self .N): if self .mat[i][j] = = num: return False return True def unUsedInCol( self , j, num): for i in range ( self .N): if self .mat[i][j] = = num: return False return True def fillRemaining( self , i, j): # Check if we have reached the end of the matrix if i = = self .N - 1 and j = = self .N: return True # Move to the next row if we have reached the end of the current row if j = = self .N: i + = 1 j = 0 # Skip cells that are already filled if self .mat[i][j] ! = 0 : return self .fillRemaining(i, j + 1 ) # Try filling the current cell with a valid value for num in range ( 1 , self .N + 1 ): if self .checkIfSafe(i, j, num): self .mat[i][j] = num if self .fillRemaining(i, j + 1 ): return True self .mat[i][j] = 0 # No valid value was found, so backtrack return False def removeKDigits( self ): count = self .K while (count ! = 0 ): i = self .randomGenerator( self .N) - 1 j = self .randomGenerator( self .N) - 1 if ( self .mat[i][j] ! = 0 ): count - = 1 self .mat[i][j] = 0 return def printSudoku( self ): for i in range ( self .N): for j in range ( self .N): print ( self .mat[i][j], end = " " ) print () # Driver code if __name__ = = "__main__" : N = 9 K = 40 sudoku = Sudoku(N, K) sudoku.fillValues() sudoku.printSudoku() |
C#
/* C# program for Sudoku generator */ using System; public class Sudoku { int [,] mat; int N; // number of columns/rows. int SRN; // square root of N int K; // No. Of missing digits // Constructor public Sudoku( int N, int K) { this .N = N; this .K = K; // Compute square root of N double SRNd = Math.Sqrt(N); SRN = ( int )SRNd; mat = new int [N,N]; } // Sudoku Generator public void fillValues() { // Fill the diagonal of SRN x SRN matrices fillDiagonal(); // Fill remaining blocks fillRemaining(0, SRN); // Remove Randomly K digits to make game removeKDigits(); } // Fill the diagonal SRN number of SRN x SRN matrices void fillDiagonal() { for ( int i = 0; i<N; i=i+SRN) // for diagonal box, start coordinates->i==j fillBox(i, i); } // Returns false if given 3 x 3 block contains num. bool unUsedInBox( int rowStart, int colStart, int num) { for ( int i = 0; i<SRN; i++) for ( int j = 0; j<SRN; j++) if (mat[rowStart+i,colStart+j]==num) return false ; return true ; } // Fill a 3 x 3 matrix. void fillBox( int row, int col) { int num; for ( int i=0; i<SRN; i++) { for ( int j=0; j<SRN; j++) { do { num = randomGenerator(N); } while (!unUsedInBox(row, col, num)); mat[row+i,col+j] = num; } } } // Random generator int randomGenerator( int num) { Random rand = new Random(); return ( int ) Math.Floor(( double )(rand.NextDouble()*num+1)); } // Check if safe to put in cell bool CheckIfSafe( int i, int j, int num) { return (unUsedInRow(i, num) && unUsedInCol(j, num) && unUsedInBox(i-i%SRN, j-j%SRN, num)); } // check in the row for existence bool unUsedInRow( int i, int num) { for ( int j = 0; j<N; j++) if (mat[i,j] == num) return false ; return true ; } // check in the row for existence bool unUsedInCol( int j, int num) { for ( int i = 0; i<N; i++) if (mat[i,j] == num) return false ; return true ; } // A recursive function to fill remaining // matrix bool fillRemaining( int i, int j) { // System.out.println(i+" "+j); if (j>=N && i<N-1) { i = i + 1; j = 0; } if (i>=N && j>=N) return true ; if (i < SRN) { if (j < SRN) j = SRN; } else if (i < N-SRN) { if (j==( int )(i/SRN)*SRN) j = j + SRN; } else { if (j == N-SRN) { i = i + 1; j = 0; if (i>=N) return true ; } } for ( int num = 1; num<=N; num++) { if (CheckIfSafe(i, j, num)) { mat[i,j] = num; if (fillRemaining(i, j+1)) return true ; mat[i,j] = 0; } } return false ; } // Remove the K no. of digits to // complete game public void removeKDigits() { int count = K; while (count != 0) { int cellId = randomGenerator(N*N)-1; // System.out.println(cellId); // extract coordinates i and j int i = (cellId/N); int j = cellId%9; if (j != 0) j = j - 1; // System.out.println(i+" "+j); if (mat[i,j] != 0) { count--; mat[i,j] = 0; } } } // Print sudoku public void printSudoku() { for ( int i = 0; i<N; i++) { for ( int j = 0; j<N; j++) Console.Write(mat[i,j] + " " ); Console.WriteLine(); } Console.WriteLine(); } // Driver code public static void Main( string [] args) { int N = 9, K = 20; Sudoku sudoku = new Sudoku(N, K); sudoku.fillValues(); sudoku.printSudoku(); } } // This code is contributed by rrrtnx. |
Javascript
// JS program to implement the approach class Sudoku { // Constructor constructor(N, K) { this .N = N; this .K = K; // Compute square root of N const SRNd = Math.sqrt(N); this .SRN = Math.floor(SRNd); // Initialize all entries as false to indicate // that there are no edges initially this .mat = Array.from({ length: N }, () => Array.from({ length: N }, () => 0)); } // Sudoku Generator fillValues() { // Fill the diagonal of SRN x SRN matrices this .fillDiagonal(); // Fill remaining blocks this .fillRemaining(0, this .SRN); // Remove Randomly K digits to make game this .removeKDigits(); } // Fill the diagonal SRN number of SRN x SRN matrices fillDiagonal() { for (let i = 0; i < this .N; i += this .SRN) { // for diagonal box, start coordinates->i==j this .fillBox(i, i); } } // Returns false if given 3 x 3 block contains num. unUsedInBox(rowStart, colStart, num) { for (let i = 0; i < this .SRN; i++) { for (let j = 0; j < this .SRN; j++) { if ( this .mat[rowStart + i][colStart + j] === num) { return false ; } } } return true ; } // Fill a 3 x 3 matrix. fillBox(row, col) { let num = 0; for (let i = 0; i < this .SRN; i++) { for (let j = 0; j < this .SRN; j++) { while ( true ) { num = this .randomGenerator( this .N); if ( this .unUsedInBox(row, col, num)) { break ; } } this .mat[row + i][col + j] = num; } } } // Random generator randomGenerator(num) { return Math.floor(Math.random() * num + 1); } // Check if safe to put in cell checkIfSafe(i, j, num) { return ( this .unUsedInRow(i, num) && this .unUsedInCol(j, num) && this .unUsedInBox(i - (i % this .SRN), j - (j % this .SRN), num) ); } // check in the row for existence unUsedInRow(i, num) { for (let j = 0; j < this .N; j++) { if ( this .mat[i][j] === num) { return false ; } } return true ; } // check in the row for existence unUsedInCol(j, num) { for (let i = 0; i < this .N; i++) { if ( this .mat[i][j] === num) { return false ; } } return true ; } // A recursive function to fill remaining // matrix fillRemaining(i, j) { // Check if we have reached the end of the matrix if (i === this .N - 1 && j === this .N) { return true ; } // Move to the next row if we have reached the end of the current row if (j === this .N) { i += 1; j = 0; } // Skip cells that are already filled if ( this .mat[i][j] !== 0) { return this .fillRemaining(i, j + 1); } // Try filling the current cell with a valid value for (let num = 1; num <= this .N; num++) { if ( this .checkIfSafe(i, j, num)) { this .mat[i][j] = num; if ( this .fillRemaining(i, j + 1)) { return true ; } this .mat[i][j] = 0; } } // No valid value was found, so backtrack return false ; } // Print sudoku printSudoku() { for (let i = 0; i < this .N; i++) { console.log( this .mat[i].join( " " )) } } // Remove the K no. of digits to // complete game removeKDigits() { let count = this .K; while (count !== 0) { // extract coordinates i and j let i = Math.floor(Math.random() * this .N); let j = Math.floor(Math.random() * this .N); if ( this .mat[i][j] !== 0) { count--; this .mat[i][j] = 0; } } return ; } } // Driver code let N = 9 let K = 40 let sudoku = new Sudoku(N, K) sudoku.fillValues() sudoku.printSudoku() // This code is contributed by phasing17. |
Output: [0 means not filled]
2 3 0 4 1 5 0 6 8 0 8 0 2 3 6 5 1 9 1 6 0 9 8 7 2 3 4 3 1 7 0 9 4 0 2 5 4 5 8 1 2 0 6 9 7 9 2 6 0 5 8 3 0 1 0 0 0 5 0 0 1 0 2 0 0 0 8 4 2 9 0 3 5 9 2 3 7 1 4 8 6
Time Complexity: O(N2)
Auxiliary Space: O(N2), since N2 extra space has been taken.
This article is contributed by Aarti_Rathi and Ankur Trisal (ankur.trisal@gmail.com). If you like GeeksforGeeks and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Please Login to comment...