Sudoku Solver in C++ partially solving - c++

I recently made a sudoku solver in c++. I used a backtracking algorithm to solve it, but there is a problem : for some cases it only solves up to the 5th row.
Working case : [6][6] = 2, [4][5] = 1
Case failing after row 5 : [1][1] = 1
I don't know what might be the reason it is partially solving the sudoko for some cases and there exist soloution for that cases
using namespace std;
#include<iostream>
int a[9][9],b[9][9];
bool searchrow(int i,int w,int p){
int q=0;
for(int j=0;j<9;j++){
if(j==w){
continue;
}
if(a[i][j]==p){
q=1;break;
}
}
if(q==1){
return false;
}
else
return true;
}
bool searchcoloumn(int i,int w,int p){
int q=0;
for(int j=0;j<9;j++){
if(j==w){
continue;
}
if(a[j][i]==p){
q=1;break;
}
}
if(q==1){
return false;
}
else
return true;
}
bool searchmatrix(int i,int j,int p){
int m,n,x,y,l,k,q;
m=(i/3)*3;
n=(j/3)*3;
x=m+2;
y=n+2;
q=0;
for(l=m;l<=x;l++){
for(k=n;k<=y;k++){
if(l==i&&k==j){ //skip the current location
continue;
}
if(a[l][k]==p){
q=1;
break;
}
}
}
if(q==0){
return true;
}
else
return false;
}
bool place(int i,int j,int p){
if(searchrow(i,j,p)&&searchcoloumn(j,i,p)&&searchmatrix(i,j,p)){
return true;
}
else{
return false;
}
}
bool sudoko(int i,int j){
int w,x;
for(int p=1;p<10;p++){
x=0;
if(place(i,j,p)){
if(b[i][j]==0){
a[i][j]=p;
}
if((i==8)&&(j==8)){
return true;
}
else if(j==8){
sudoko(i+1,0);
}
else{
sudoko(i,j+1);//move to next coloumn
}
}
}
}
int main(){
int i,j,t,data;
cout<<"\nEnter how many no. to add to sudoko\n";
cin>>t;//t is the no of element which are initially present in sudoko and user should give as input
cout<<"\nEnter row , coloumn and then data at the respective location\n";
for(int m=0;m<9;m++){
for(int n=0;n<9;n++){
a[m][n]=0;
b[m][n]=0;
}
}
while(t--){
cout<<"Enter row";
cin>>i;
cout<<"Enter coloumn";
cin>>j;
cout<<"Enter data";
cin>>data;
a[i][j]=data;
b[i][j]=data;
}
if(sudoko(0,0));//used a semicolon here so that to display result
for(int p=0;p<9;p++){
cout<<"\n"
for(int q=0;q<9;q++){
cout<<a[p][q]<<"\t";
}
}
}

In sudoko(int, int) you perform two recursive calls, then drop out of the function without returning a value, which is undefined behaviour. You probably want to replace each call by return sudoko(...), and crank up your compiler warnings.

Related

codechef isrec wrong answer

I am facing a wrong answer on my submission. I have run all the test cases that came to my mind but unfortunately all seem to give the correct output.
I even checked out others' submissions but didn't get very far. Apparently idea seems to be fine but maybe I am missing some serious detail. I simply have no idea.
The link to the question is:
https://www.codechef.com/CCRC21C/problems/ISREC
My code is:
#include<bits/stdc++.h>
using namespace std;
int num_consec_ones(string row,int m)
{
int c=0;
for(int i=0;i<m;i++)
{
if(row[i]==1) c++;
if(c>1 && row[i-1]==0 && row[i]==1)
{
c=-1;
break;
}
}
return c;
}
int start_index(string row,int m)
{
for (int i=0;i<m;i++)
{
if(row[i]==1)
return i;
}
}
void solve()
{
int n,m,flag=0;;
cin>>n>>m;
vector<string>row;
// row.reserve(n);
for(int i=0;i<n;i++)
{
string str;
cin>>str;
row.push_back(str);
for(int j=0;j<m;j++)
row[i][j]=row[i][j]-'0';
}
set<int>s;
for(int j=0;j<n;j++)
{
if(num_consec_ones(row[j],m)==-1)
{
cout<<"No"<<endl;
return;
}
if(num_consec_ones(row[j],m) && flag==1 && num_consec_ones(row[j-1],m)==0)
{
cout<<"No"<<endl;
return;
}
if(num_consec_ones(row[j],m) && flag==0)
{
s.insert(num_consec_ones(row[j],m));
flag=1;
}
}
if(s.size()==1)
{
set<int>start;
for(int j=0;j<n;j++)
{
if(num_consec_ones(row[j],m))
{
start.insert(start_index(row[j],m));
}
}
if(start.size()==1)
{
cout<<"Yes"<<endl;
return;
}
else{
cout<<"No"<<endl;
return;
}
}
}
int main()
{
int t;
cin>>t;
while(t--)
{
solve();
}
}
Please help me out.
Thank you!

I have written a C++ program to solve sudoku puzzle ,it is showing "Exception has occurred. EXC_BAD_ACCESS"

Here is the code I have written:
#include<iostream>
using namespace std;
int puzzle[9][9]=
{
{0,5,0,0,6,2,7,0,0},
{0,0,0,0,0,0,1,0,2},
{7,0,9,3,0,0,0,0,0},
{3,0,0,0,8,0,0,0,0},
{0,8,0,7,0,9,0,2,0},
{0,0,0,0,5,0,0,0,7},
{0,0,0,0,0,6,2,0,8},
{2,0,6,0,0,0,0,0,0},
{0,0,3,4,2,0,0,9,0},
};//puzzle template
bool row_possible(int row,int number);//To find out whether a number is possible in the particular row
bool column_possible(int column,int number);//To find whether a number is possible in the particular column
bool square_possible(int row,int column,int number);//To find whether a number is possible in its square
bool possible(int row,int column,int number);//To find whether a number is possible in the given position
bool unassigned();//To check whether the puzzle has any unassigned spaces
void printSolution();//To print the final solution to the console
bool solve();//To solve the puzzle
int main()
{
if(solve())
printSolution();
else
cout<<"\nNo Solution";
return 0;
}
bool row_possible(int row,int number)
{
int m=0;
for(int column=0;column<9;column++)
{
if(puzzle[row-1][column]==number)
m++;
}
if(m!=0)
return false;
else
{
return true;
}
}
bool column_possible(int column,int number)
{
int m=0;
for(int row=0;row<9;row++)
{
if(puzzle[row][column-1]==number)
m++;
}
if (m!=0)
return false;
else
{
return true;
}
}
bool square_possible(int row,int column,int number)
{
int mod_x=(row-1)%3,mod_y=(column-1)%3;
int i=(row-1)-mod_x,j=(column-1)-mod_y;
int m=0;
int k=0;
int check_x=3,check_y=3;
for(k=0;check_x!=0;check_x--)
{
for(k=0;check_y!=0;check_y--)
{
if(puzzle[i][j]==number)
m++;
j++;
}
i++;
}
if(m!=0)
return false;
else
{
return true;
}
}
bool possible(int row,int column,int number)
{
if(row_possible(row,number)&&column_possible(column,number)&&square_possible(row,column,number))
return true;
else
{
return false;
}
}
bool unassigned()
{
int m=0;
for(int row=0;row<9;row++)
{
for(int column=0;column<9;column++)
{
if(puzzle[row][column]==0)
m++;
}
}
if(m>0)
return true;
else
{
return false;
}
}
void printSolution()
{
for(int i=0;i<9;i++)
{
for(int j=0;j<9;j++)
{
cout<<puzzle[i][j]<<" ";
}
cout<<"\n";
}
}
bool solve()
{
if(!unassigned())
return true;
for(int row=1;row<10;row++)
{
for(int column=1;column<10;column++)
{
for(int number=1;number<10;number++)
{
if(possible(row,column,number))
{
puzzle[row-1][column-1]=number;
if(solve())
return true;
puzzle[row-1][column-1]=0;
}
}
}
}
return false;
}
The debugger is throwing the error in:
int m=0;
int k=0;
int check_x=3,check_y=3;
It says Exception has occurred.
EXC_BAD_ACCESS.It also says that read memory is failed.
I dont understand what it says.Let me also know whether my program needs any improvements
Kindly help me.I am using Visual Studio Code on MacOS.Thank You
You can do a simple calculation on how long it would take for you to get an answer.
You have 55 open cells that you try 9 different numbers. This gives you 955 = 3 * 1052 tries.
If one try takes 1μs it will take ~ 9.6 * 1038 years to find a solution.
I have written a C++ program and that finds a solution of this sudoku in 30ms and my PC is not a very fast one (5 years old) and 10ms of this is used to print the solution to screen with printf

linear search on array of object c++

i have a problem with a function ..
I want the function to have two arguments ..
one will be a array of objects and the second one will be the code given by the user
and into the function to run a linear search and check if the user's code exists and if the code exists will return his position in the array else returns -1...
this is what i have try already:
int passwdSearch(Eidos pinPro[], int pass)
{
int i=0;
bool found;
found=false;
while(i<N && found==false)
{
if(pinPro[i].getPasswd()==pass)
{
found=true;
return i;
}
else
return -1;
i++;
}
}
i want the function return the position if password exist else return symbolic number -1
The problem is that the code return position only for the first element of array and for the 4 others element function return -1
Try this:
int passwdSearch(Eidos pinPro[], int pass)
{
for(int i=0; i<N; i++)
{
if(pinPro[i].getPasswd()==pass)
return i;
}
return -1;
}
Try this code
int passwdSearch(Eidos pinPro[], int pass)
{
int i=0;
bool found;
found=false;
while(i<N && found==false)
{
if(pinPro[i].getPasswd()==pass)
{
found=true;
return i;
}
else
i++;
}
return -1;
}
The else will always be activated if the element is not the first one in the array. you should delete it, and return -1 after the while.
int passwdSearch(Eidos pinPro[], int pass)
{
int i=0;
bool found;
found=false;
while(i<N && found==false)
{
if(pinPro[i].getPasswd()==pass)
{
found=true;
return i;
}
}
return -1;
}
This way, if you pass through the whole array and you don't find the required element, then you would return -1.
Edit
And as NathanOliver mentioned, found is useless because you are returning anyways when you find an element. So the code becomes:
int passwdSearch(Eidos pinPro[], int pass)
{
int i=0;
while(i<N)
{
if(pinPro[i].getPasswd()==pass)
return i;
i++;
}
return -1;
}

pop() is not working properly

Here is a c++ code on stack.Ignore the extra code here
#include<iostream>
using namespace std;
class mystack
{
private:
int top;
int size;
int * s;
public:
void initialize()
{
top=-1;
cin>>size;
s=new int[size];
}
~mystack(){delete [] s;}
void push()
{
int x;
if(top==size-1)
cout<<"stack overflow!"<<endl;
else
{
cout<<"Enter element to be pushed:";
cin>>x;
top++;
s[top]=x;
cout<<s[top]<<endl;
}
}
int pop()
{
int p=s[top];
if(top==-1)
return 0;
else
{
top--;
return p;
}
}
int maxsize()
{
return size;
}
int isempty()
{
if(top==-1)
return 0;
else
return 1;
}
void display()
{
int i,p=top;
cout<<s[0]<<endl;
for(i=0;i<=p;i++)
cout<<s[i]<<endl;
}
};
int main()
{
int n,i;
cout<<"Enter no. of stacks:";
cin>>n;
mystack * st=new mystack[n];
for(i=0;i<n;i++)
{
cout<<"Enter size of stack "<<i+1<<":";
st[i].initialize();
}
int c,s;
while(1)
{
cout<<"*****Operations*****"<<endl;
cout<<"1.Push 2.Pop 3.Maxsize 4.isempty 5.Display 6.Quit"<<endl;
cout<<"Enter your choice:";
cin>>c;
if(n>1)
{
cout<<"Operation on which stack:";
cin>>s;
}
else
s=1;
if(c==1)
st[s-1].push();
else if(c==2)
{
if(st[s-1].pop()==0)
cout<<"stack underflow!"<<endl;
else
cout<<st[s-1].pop()<<endl;
}
else if(c==3)
cout<<st[s-1].maxsize()<<endl;
else if(c==4)
{
if(st[s-1].isempty()==0)
cout<<"True"<<endl;
else
cout<<"False"<<endl;
}
else if(c==5)
st[s-1].display();
else if(c==6)
break;
else
{
cout<<"Wrong input!"<<endl;
continue;
}
}
return 0;
}
Here accessing pop operation gives the element of top-1.I can't understand why.What should I do?When I do return s[top--] same thing is happening.
Since you haven't gotten back to this, I am going to presume you've already found your logic error.
So here is the one error I found. There may be more, I quit looking ...
In the following code, how many times is pop() being called?
else if(c==2)
{
if(st[s-1].pop()==0)
cout<<"stack underflow!"<<endl;
else
cout<<st[s-1].pop()<<endl;
}

How to proceed further in this 8 queen algorithm?

The code and output is working fine before backtracking but I am not able to proceed for backtracking. What to do do after unplacing? It is giving the output of first 4 queens only means before backtracking.
#include <iostream>
#include <conio.h>
using namespace std;
int recu(int i,int k);
void place(int i,int k);
void unplace(int i,int k);
int q[8][8];
int row[8];
int column[8];
int c[15];
int d[15];
int totalqueens=0;
int s;
int main()
{
for(int i=0;i<8;i++) //Flags for rows,columns and diagonals
{
row[i]=0;
column[i]=0;
c[i]=0;d[i]=0;
}
for(int i=8;i<15;i++)
{
c[i]=0;d[i]=0;
}
int i=0;
int k=0;
recu(i,k);
for(int i=0;i<8;i++)
{
for(int k=0;k<8;k++)
{
if(q[i][k]==1)
{
cout<<"(";
cout<<i;
cout<<",";
cout<<k;
cout<<")";
}
}
}
getch();
return 0;
}
int recu(int i,int k)
{
if(totalqueens==8)
{ goto print; }
if(k<8)
{
if(column[i]==0 && row[k]==0 && c[i+k]==0 && d[i-k+7]==0)
{
place(i,k);
s=k;
k=0;
recu(i+1,k);
}
else
{
recu(i,k+1);
unplace(i-1,s);
//**I am not able to proceed further**
}
}
print:
;
}
void place(int i,int k)
{
totalqueens++;
q[i][k]=1;
row[k]=1;
column[i]=1;
c[i+k]=1;
d[i-k+7]=1;
}
void unplace(int i,int k)
{
q[i][k]=0;
row[i]=0;
column[k]=0;
c[i+k]=0;
d[i-k+7]=0;
//cout<<"before call";
recu(i,k+1);
//cout<<"working";
}
Your code only gives out one solution.
u r not put the output part in the right place.
try like this:
void print()
{
for(int i=0;i<8;i++)
{
for(int k=0;k<8;k++)
{
if(q[i][k]==1)
{
cout<<"(";
cout<<i;
cout<<",";
cout<<k;
cout<<")";
}
}
}
}
make that to be one method. and then, in your recu method, modify to:
if(totalqueens==8)
{
print();
return;
}
Keep in mind that DO NOT use goto sentence. It is very ugly and may cause unknown problems.
You backtrack when not all queens have been placed and you cannot place another queen. You backtrack as follows:
See if the last placed queen can be placed in a later spot. If so, place it there and stop backtracking. (Resume placing.)
Remove the last placed queen.
If there are no queens left, stop. All solutions have been found.
Go to step 1.