Welcome to Dream.In.Code
Become a C++ Expert!

Join 137,428 C++ Programmers for FREE! Get instant access to thousands of C++ experts, tutorials, code snippets, and more! There are 1,902 people online right now. Registration is fast and FREE... Join Now!




Coding a Sudoku Solver

 
Reply to this topicStart new topic

Coding a Sudoku Solver

Eliah
11 Jan, 2008 - 05:40 PM
Post #1

New D.I.C Head
*

Joined: 11 Jan, 2008
Posts: 3

Hi guys!

I'm trying to complete a code of a sudoku solver. But I have no idea how it has to look like...It would be really nice if some1 could help me to complete this code.
This is, what I got (up to now). Tell me if I did a mistake... I'll post the main *.cpp-file (sudoku.cpp). The main-function has to be completed. the auxiliary and the headerfiles will follow if you need them too (generator.cpp & generator.h).


sudoku.cpp:
CODE

#include <stdlib.h>
#include <time.h>
#include <iostream>
#include "generator.h"

using namespace std;


/*Prints the grid with white spaces for unassigned cells and double-line
* delimitations for regions
*/
void print(){
     for ( int i=0; i<SIZE; i++ ){

         if ( i == 0 )
           cout<<"======================================="<<endl;        
        
        for( int j=0; j<SIZE; j++ ){
             if ( j==0 )
                cout<<"|| ";
            
             if ( grid[i][j].value != 0 ){
                  cout<<grid[i][j].value<<" |";
             }
             else{
                  cout<<"  |";
             }  
            
             if( j==SIZE-1 )
                 cout<<"|"<<endl;
             else
                 cout<<" ";
        }
        
        if ( (i+1)%3 == 0 )
           cout<<"======================================="<<endl;    
        else
            cout<<"---------------------------------------"<<endl;
     }
}


/* Checks whether the grid is correctly solved or not */
bool check(){
    
     /*For current row/column/region keep an array with the assigned values
       Examples: tempv[2] is 1 if value "3" was assigned to the current column
                 temps[3] is 0 if value "4" was not assigned to the current region */            
     int temph[SIZE] = {0};
     int tempv[SIZE] = {0};
     int temps[SIZE] = {0};
    
     for ( int i =0; i<SIZE; i++ ){
         for ( int j=0; j<SIZE; j++ ){
            
             //If cell has no value assigned yet
             if ( grid[i][j].value == 0 )
                return false;
            
             /* Check if all cells in a row have a value assigned*/
             if ( temph[grid[i][j].value - 1] != 0 )
                 return false;
             else
                 temph[grid[i][j].value - 1] = 1;
                
             if ( grid[j][i].value == 0 )
                return false;
            
             /* Check if all cells in a column have a value assigned*/
             if ( tempv[grid[j][i].value - 1] != 0 )
                 return false;
             else
                 tempv[grid[j][i].value - 1] = 1;
                                  
             if ( grid[(i/3)*3+j/3][(j%3)+3*(i%3)].value == 0 )
                return false;
                

             /* Check if all cells in a region have a value assigned*/
             if ( temps[grid[(i/3)*3+j/3][(j%3)+3*(i%3)].value - 1] != 0 )
                 return false;
             else
                 temps[grid[(i/3)*3+j/3][(j%3)+3*(i%3)].value - 1] = 1;
         }
        
         //Next row/column/region : reset arrays
         for ( int k=0; k<SIZE; k++ ){
             temph[k] = 0;
             tempv[k] = 0;
             temps[k] = 0;
         }
     }
    
     return true;
}


void solve(){

}

int main(int argc, char* argv[]){
    
    if ( argc < 2 ){
         cout<<"Usage : <executable_name> <guess_values_number>"<<endl;
         return -1;
    }

    /* Initialize random generator */
    /* If you just want a pseudo-random distr. for debugging purposes you may comment this line out */
    srand( time(NULL) );
    
    /* Initialize the grid structures */
    init();
    
    /* Generate solution */
    generator();
    
    /* Hide numbers from the solution to generate initial grid */
    hide(atoi(argv[1]));
    
    cout<<endl;
    
    cout<<"Initial grid : "<<endl<<endl;
    
    /* Print the initial grid to be solved */
    print();
    
    cout<<endl;
    
    /* Solve the grid */
    solve();
    
    /* Print the solution if one was found */
    if (check()){
          cout<<"Solved grid : "<<endl<<endl;
          print();
          cout<<endl;
    }

    return 0;
}



Now, I know what the programm has to do, but I have no idea how to write it in c++...
This steps are missing and should be added:


1. Each initially given number is assigned to its corresponding cell, while eliminating that number from the list of possibilities of the cells belonging to the same row/column/region
2. All cells with one possibility of choice are assigned the corresponding number; this number is eliminated from the other cells in the same row/column/region.
3. If there are no more cells with only one possibility and there are still empty (unassigned) cells, then return with message "No solution"
4. If all values are assigned, return and print solution

Any Hints? Or frameworks how it has to look like?
User is offlineProfile CardPM
+Quote Post

VernonDozier
RE: Coding A Sudoku Solver
11 Jan, 2008 - 10:51 PM
Post #2

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

I think you'll have to post the other files in order for other people to successfully help you since your "main" file is referring to functions and constants named in the other files and thus won't compile. Are you looking for ideas on the sudoku algorithm itself or just help on the code to implement it? It looks like you've decided on the algorithm you want to use but just want help on how to implement it in C++.


User is offlineProfile CardPM
+Quote Post

harshakirans
RE: Coding A Sudoku Solver
12 Jan, 2008 - 01:02 AM
Post #3

D.I.C Head
Group Icon

Joined: 26 Apr, 2006
Posts: 122



Thanked: 3 times
Dream Kudos: 150
My Contributions
Hey why dont you refer the snippet which i submitted(sudoku solver) This wil give you an new easier approach to solve the problem. http://www.dreamincode.net/code/snippet419.htm ..
User is offlineProfile CardPM
+Quote Post

Eliah
RE: Coding A Sudoku Solver
12 Jan, 2008 - 01:53 AM
Post #4

New D.I.C Head
*

Joined: 11 Jan, 2008
Posts: 3

QUOTE
Are you looking for ideas on the sudoku algorithm itself or just help on the code to implement it? It looks like you've decided on the algorithm you want to use but just want help on how to implement it in C++.


Yes, I need help on the code to implement it (points 1-4).


Here are the other files:

generator.cpp:
CODE
#include <stdlib.h>
#include <math.h>
#include "generator.h"

/* Two-dimensional array of cells*/
cell grid[SIZE][SIZE];

/* Initialize all the cells;
* No number assigned, so "value" is "0" for all
* The number of value possibilities is maximum : 9
* Initialize the list of possible values that the cell can take : 1-9
*/
void init(){
     for ( int i=0; i<SIZE; i++ ){
        for( int j=0; j<SIZE; j++ ){
             cell tcell;
             tcell.value = 0;            
             grid[i][j] = tcell;            
        }
     }
}

/* Start with a solution and "hide" a random number "no" of values from the grid */
void hide(int no){
    
     for ( int i=1; i<=no; i++ ){
        
         /* Randomly generate a position in the grid */
         int x = rand()%SIZE;
         int y = rand()%SIZE;
        
         int done = false;
        
         /* If the current cell was already hidden, repeat until we find a visible one */
         while(!done){
             if ( grid[x][y].value != 0 ){
                  done = true;
                  grid[x][y].value = 0;
             }
             else{
                  x = (rand()+x)%SIZE;
                  y = (rand()+y)%SIZE;
             }
          }
        
        
     }
}

/* Randomly generate a list of values 1-9 which we assign to the top-left region */
void generateFirstRegion(){
    
     int temp[SIZE] = {0};
    
     for ( int i=0; i<SIZE; i++ ){
        
         int crt_digit = rand()%SIZE;
        
         while ( temp[crt_digit] != 0 ){
               crt_digit = (crt_digit+rand())%SIZE;
         }
        
         temp[crt_digit] = 1;        
         grid[i/3][i%3].value = crt_digit + 1;
     }
}

/* Generate a region on the right side of a already generated one by rotating the
*  values of rows
*  Example: 1 2 3              4 5 6
            4 5 6    becomes   7 8 9
            7 8 9              1 2 3
*/
void generateHorizontalRegion(int x,int y){    
     for ( int i=0; i<SIZE; i++ ){
         grid[i/3+3*y][i%3+3*x].value = grid[(i/3+x)%3+3*y][i%3].value;
     }    
}

/* Generate a region underneath the top-left one by rotating the values of the columns
*  Example: 1 2 3
            4 5 6
            7 8 9
            
            becomes
            
            2 3 1
            5 6 4
            8 9 7
*/
void generateVerticalRegion(int x){
     for ( int i=0; i<SIZE; i++){
         grid[i/3+3*x][i%3].value = grid[i/3][(i+x)%3].value;
     }
}

/* Generator function; the result is represented by a solution grid */
void generator(){
    
    generateFirstRegion();
    
    generateHorizontalRegion(1,0);
    generateHorizontalRegion(2,0);
        
    generateVerticalRegion(1);
  
    generateHorizontalRegion(1,1);
    generateHorizontalRegion(2,1);
  
    generateVerticalRegion(2);
      
    generateHorizontalRegion(1,2);
    generateHorizontalRegion(2,2);
}



and the header file:
generator.h:
CODE
const int SIZE = 9;

/* Structure defining a cell in the grid */
struct cell{
       unsigned short value; //value assigned to this cell (0 if no value assigned)
};

/* declaration  of global variable grid */
extern cell grid[SIZE][SIZE];



/* Initialize all the cells;
* No number assigned, so "value" is "0" for all
* The number of value possibilities is maximum : 9
* Initialize the list of possible values that the cell can take : 1-9
*/
void init();

/* Start with a solution and "hide" a random number "no" of values from the grid */
void hide(int no);


/* Randomly generate a list of values 1-9 which we assign to the top-left region */
void generateFirstRegion();

/* Generate a region on the right side of a already generated one by rotating the
*  values of rows
*  Example: 1 2 3              4 5 6
            4 5 6    becomes   7 8 9
            7 8 9              1 2 3
*/
void generateHorizontalRegion(int x,int y);

/* Generate a region underneath the top-left one by rotating the values of the columns
*  Example: 1 2 3
            4 5 6
            7 8 9
            
            becomes
            
            2 3 1
            5 6 4
            8 9 7
*/
void generateVerticalRegion(int x);

/* Generator function; the result is represented by a solution grid */
void generator();

User is offlineProfile CardPM
+Quote Post

VernonDozier
RE: Coding A Sudoku Solver
12 Jan, 2008 - 12:34 PM
Post #5

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

Well, I think you should have seven functions. Please use scroll bar to see entire code since it doesn't all fit on the screen:

CODE


// returns row number with exactly one missing cell in the row.  Returns -1 if none exist yet.
int FindRowReadyToSolve ();

// returns column number with exactly one missing cell in column.  Returns -1 if none exist yet
int FindColumnReadyToSolve ();

// returns true if there is a box ready to be solved.  row and column are set to upper left corner of box.
// returns false otherwise
bool FindBoxReadyToSolve (int& row, int& column);

// given a row with eight entries, fills in missing entry
void Solve Row (int row);

// given a column with eight entries, fills in missing entry
void SolveColumn (int column);

// given a box with eight entries, fills in missing entry
// row and column are upper left coordinates of box
void SolveBox (int row, int column);

// Traverses columns, rows, and boxes for duplicates.  Returns false if
// illegal entry exists, true otherwise
bool CheckIf Legal ();



For a brute force solution, continually call FindRowReadyToSolve, FindColumnReadyToSolve, and FindBoxReadyToSolve. If none of them give you anything ready to solve, by your algorithm, it is unsolvable. If you find one ready to solve, call the appropriate function to fill in the missing cell. After each time when you fill a new cell and solve it, call CheckIfLegal. If you have an illegal entry, by your algorithm, it's unsolvable.

Anyway, I think that's a decent way of approaching it using your algorithm. You might want to consider changing algorithms as I believe yours will miss some solutions and there are more efficient ones (albeit probably more complex), but if you want to stick with that one, this may work. There are also a lot of earlier posts on similar problems on this site, so they may give you some other ideas as well. Good luck. Am I understanding your algorithm correctly? Also, this is one way, but not the only way to do it.
User is offlineProfile CardPM
+Quote Post

VernonDozier
RE: Coding A Sudoku Solver
12 Jan, 2008 - 12:59 PM
Post #6

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

Just reread your algorithm. I think I missed part of it earlier. It will find more solutions than I realized earlier. The seven functions will work, but your algorithm requires more. Perhaps you should set up a three dimensional boolean array, initially all true:

bool possible[SIZE][SIZE][SIZE];


The first two arguments will be row and column. The last will be whether it is "legal" to place that particular number in that cell. For example,

possible[2][4][6] would be true if it is okay to put a 7 in row 3, column 5 (adding 1 to each index since indexes start at 0 and rows, columns, and cell entries start at 1). Each time you add a new entry, a lot of these entries will be set to false. If you can't find a row, column, or box with only one missing entry, you can traverse this 3-D array. If there is only one "true" value in this array for a given row and column (i.e. only one possible solution to that row and column), you can fill in that cell with that value and move on. It will thus find solutions that were "unsolvable" earlier. It's still a brute force solution but will find more answers.
User is offlineProfile CardPM
+Quote Post

Eliah
RE: Coding A Sudoku Solver
12 Jan, 2008 - 05:37 PM
Post #7

New D.I.C Head
*

Joined: 11 Jan, 2008
Posts: 3

First of all, thank you VernonDozier for your posts. I'll give some thoughts to ur version. I just want to program a code which can solve easy sudokus. I thought, that this would be possible with my algorithm?!?
User is offlineProfile CardPM
+Quote Post

VernonDozier
RE: Coding A Sudoku Solver
12 Jan, 2008 - 10:26 PM
Post #8

New D.I.C Head
*

Joined: 6 Jan, 2008
Posts: 46

I think your algorithm does work fine for easy sudoku problems and my suggestions (I hope) correspond to your algorithm. There are a whole bunch of algorithms out there to solve sudoku but I tried to tailor my comments to your algorithm, which I think can solve quite a few sudoku problems.

User is offlineProfile CardPM
+Quote Post

Reply to this topicStart new topic
Time is now: 12/5/08 04:50AM

Live C++ Help!

C++ Tutorials

Reference Sheets

C++ Snippets

DIC Chatroom

Bye Bye Ads

Monthly Drawing

Thumb Drive

Top Contributors

Top 10 Kudos This Month