solve sudoku with backtracking - C++ - c++

So I am trying to solve sudoku with backtracking
And with this example :
example_pic
I hard-coded some of the indexes in the two dimensional array with numbers on places given from webSudoku (picture above).
It definitely has solutions but, my code prints "solution doesn't exist
Here is my code :
#include <stdio.h>
int a[10][10]= {{2,0,0,0,9,0,0,3,1},
{0,0,3,5,0,6,0,2,0},
{0,0,8,1,3,0,5,4,0},
{7,2,0,0,0,9,0,0,4},
{4,0,0,0,0,0,0,0,8},
{3,0,0,6,0,0,0,9,5},
{0,7,6,0,4,5,1,0,0},
{0,1,0,9,0,7,4,0,0},
{5,3,0,0,8,0,0,0,6}};
bool is_valid(int x, int y, int value){
if(a[x][y] != 0) return false;
//check_row and column
for(int tmp=1; tmp<=9; tmp++){
if(value == a[x][tmp]) return false;
}
for(int tmp=1; tmp<=9; tmp++){
if(value == a[tmp][y]) return false;
}
//check in 3*3 block
int x_s = (x-1)/3*3 + 1;
int y_s = 3*((y+2)/3-1)+1;
for(int ch_x = x_s; ch_x<x_s+3; ch_x++){
for(int ch_y=y_s; ch_y<y_s+3; ch_y++){
if(ch_x!=x && ch_y!=y){
if(value==a[ch_x][ch_y]) return false;
}
}
}
return true;
}
bool find(int &x, int &y){
// check if valid cells are exists
for(x=1; x<=9; x++){
for(y=1; y<=9; y++){
if(a[x][y] == 0)
return true;
}
}
return false;
}
bool solve(){
int x,y;
//base::case
if(!find(x,y)) return true;
for(int cand = 1; cand <=9; cand++){
if(is_valid(x,y,cand)){
a[x][y] = cand;
if(solve()) return true;
a[x][y] = 0;
}
}
return false;
}
void print(){
//print the sudoku plate
for(int i=1;i<=9; i++){
for(int j=1; j<=9; j++){
printf("%2d",a[i][j]);
}
printf("\n");
}
return ;
}
int main(){
//Fill in some empty grid with the known values
/*for(int i=1; i<=9; i++){
for(int j=1; j<=9; j++){
scanf("%1d",&a[i][j]);
}
}*/
if (solve()) print();
else printf("No solution exists\n");
return 0;
}
I guess my 'solve function' or 'is_valid' function is not working right.
In 'is_valid' function, if there is problem it would be
bool find(int &x, int &y){
// check if valid cells are exists
for(x=1; x<=9; x++){
for(y=1; y<=9; y++){
if(a[x][y] == 0)
return true;
}
}
return false;
}
But, I also hard-coded this part and in my scope it doesn't seem like have problem.
In 'solve function'
bool solve(){
int x,y;
//base::case
if(!find(x,y)) return true;
for(int cand = 1; cand <=9; cand++){
if(is_valid(x,y,cand)){
a[x][y] = cand;
if(solve()) return true;
a[x][y] = 0;
}
}
return false;
}
I cant figure out where i got it wrong. If you find any other mistakes in the solve() function - let me know. Because I am not sure I understand the "backtracking" thing completely...
p.s. : reference I read (https://see.stanford.edu/materials/icspacs106b/H19-RecBacktrackExamples.pdf)

There are a few mistakes
You are mixing up (x, y) and (row, col) addressing (row is y, not x). Choose a representation and stick to it
There is a typo in is_valid because the check on (c, x) should be on (c, y) (or (y, c) depending on convention but surely using y and not x again)
The 3x3 sub-block computation is wrong... a correct formula could be for example int start_x = (x-1)/3*3 + 1, start_y = (y-1)/3*3 + 1;
Fixing all that the code works on the given example

Related

Memoization Approach for Gold Mine Problem on GFG

I am trying to solve the Gold Mine problem on GFG using a memoization based approach of dynamic programming. Here is the code I have written.
int dp[50][50];
int traverse(int x,int y,int n,int m, vector<vector<int>> M){
if((x<n and x>=0) and (y<m and y>=0))
{
if(dp[x][y]!=-1)
return dp[x][y];
else{
int right=M[x][y]+traverse(x,y+1,n,m,M);
int right_up=M[x][y]+traverse(x-1,y+1,n,m,M);
int right_down=M[x][y]+traverse(x+1,y+1,n,m,M);
return dp[x][y]=max(max(right,right_up),right_down);}
}
return 0;
}
int maxGold(int n, int m, vector<vector<int>> M)
{
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
dp[i][j]=-1;
}
}
int ans=0;
for(int i=0;i<n;i++){
ans=max(ans,traverse(i,0,n,m,M));
}
return ans;
}
The question says that we can start from any cell in the first column.
As the specific cell is not specified, I have tried finding out the maximum of all possible answers with each cell of the first column as the starting point. But this is giving a TLE, which is expected because the above code would take o(n^2*m) time.
Can anyone help me out with how to get around this problem of optimally figuring out which cell to start from so that the memoization based approach works under the time constraints provided?
Use call by const reference for the STL container. You performed thousands of copies of the full, read-only input.
int dp[55][55];
int traverse(int x,int y,int n,int m, const vector<vector<int>>&M){
. . .
}
int maxGold(int n, int m, const vector<vector<int>>&M)`
{
...
}
here is my solution:
class Solution{
public:
int maxGold(int n, int m, vector<vector<int>> M)
{
vector<vector<int>> f(n + 10, vector<int>(m + 10, 0));
for(int i = 0; i < n; i++){
f[i][0] = M[i][0];
}
for(int j = 1; j < m; j++){
for(int i = 0; i < n; i++){
if(i == 0){
f[i][j] = max(f[i][j-1], f[i+1][j-1]) + M[i][j];
}else if(i == n-1){
f[i][j] = max(f[i][j-1], f[i-1][j-1]) + M[i][j];
}else{
f[i][j] = max({f[i][j-1], f[i-1][j-1], f[i+1][j-1]}) + M[i][j];
}
}
}
int res = 0;
for(int i = 0; i < n; i++){
res = max(res, f[i][m-1]);
}
return res;
}
};

why am I getting segmentation fault? I am trying to solve the rat in a maze problem

why am I getting segmentation fault? I am trying to solve the rat in a maze problem.
Below is the code that is giving me the segmentation fault
May be there is some fault is passing 2D array to functions but seems alright to me
I have applied the base conditions in function rinm and passing the solution matrix as well as the user input matrix from the main().
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
}
This is my main function.
int main()
{
int n;
cin>>n;
int** maze=new int*[n];//rows
for (int i = 0; i < n; ++i)
{
maze[i]=new int [n]; // columns
}
for (int i = 0; i < n; ++i)
{
for(int j=0; j<n;j++)
{
cin>>maze[i][j];
}
}
int** sol=new int*[n];
for (int i = 0; i < n; ++i)
{
sol[i]=new int [n]; // columns
}
for (int i = 0; i < n; ++i)
{
for(int j=0; j<n;j++)
{
sol[i][j]=0;
}
}
bool path=rinm(maze,sol,n,0,0);
if(path==false)
cout<<"path doesnot exist\n";
return 0;
}
where am I going wrong?
The problem is that keep revisiting the same cells because you have not checked whether you are visiting a cell for the first time or not.
For example for the input:
2
1 1
0 1
I will enter the sequence of moves of (x, y) and you can see that it will be stuck in an infinite loop.
(0, 0)
-> (-1, 0) (up function call, returns false since x < 0)
-> (1, 0) (down function call, return false since maze[1][0] = 0)
-> (0, 1)
-> (-1, 1) (up function call, returns false since x < 0)
-> (1, 1) (down function call, solution found. Print sol matrix)
-> (0, 2) (right function call, returns false since y >= 2)
-> (0, 0) (left function call)
The problem lies here. Now you are back to (0, 0) and the recursion keeps on running without any termination. This results in huge memory allocation of recursion stack and you get Segmentation Fault.
I hope you are able to understand the problem here. If you are still in doubt, just print (x, y) as soon as you enter the loop and you will see this happening.
Here are the changes I made in the code.Here's the corrected code. This will print all available paths to reach the destination.
The function returns false if sol[x][y] == 1 which means that you have visited the cell (x, y) earlier as well.
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
return false;
}
To print any one path to the destination, you can keep a global variable and initialize that variable whenever any path is found and then return false again if that variable is initialized. The code for just one path path is below.
int c = 0;
bool rinm(int** maze,int** sol,int n, int x, int y)
{
if(x==n-1 && y==n-1)
{
c = 1;
sol[x][y]=1;
//print the path
for (int i = 0; i < n; ++i)
{
/* code */
for (int j = 0; j < n; ++j)
{
cout<<sol[i][j]<<" ";
}
cout<<endl;
}
return true;
}
else if(x<0 || y<0 || x>=n || y>=n || maze[x][y]==0 || sol[x][y]==1 || c == 1)
{
return false;
}
sol[x][y]=1;
bool up=rinm(maze,sol,n,x-1,y);
bool down=rinm(maze,sol,n,x+1,y);
bool right=rinm(maze,sol,n,x,y+1);
bool left = rinm(maze,sol,n,x,y-1);
sol[x][y]=0;
if(up||down||right||left)
{
return true;
}
return false;
}
Here are the changes represented for easy understanding.
Avoid using native 2d arrays. Replace them with a simple 1d valarray or vector and access it's elements using you own simple method that transforms x and y coords into a simple index. You'll save yourself from many headaches...
class Maze
{
private:
std::valarray<int> _data;
int _width, _height;
public:
Maze(int width, int height) : _data(width * height)
{
_width = width;
_height = height;
}
int& item(int x, int y)
{
return _data[y * _width + x];
}
// ...
}

Search Vertically and Horizontally in 2D Array

Basically I want to do a search Horizontally, and also Vertically. Right now I am doing this:
void checkHorizontal()
for (int iii = 1; iii<Row;; iii++)
{
for (int jjj = 1; jjj<Col; jjj++) //for every col
{
if(Array[iii][jjj]==sign)
{
//do something
}
else
{
//do something else
}
}
}
void checkVertical()
for (int iii = 1; iii<Col;; iii++)
{
for (int jjj = 1; jjj<Row; jjj++) //for every row
{
if(Array[jjj][iii]==sign)
{
//do something
}
else
{
//do something else
}
}
}
Yet, except the check function inside the for loop and the if statement, everything else is the same. And I want to reduce duplicate code, so what can I do to make a more generic function and caller just need to pass in saying if they want to do a Horizontal search or Vertical search (i.e. void check(string mode) and caller just check("Vertical"))
I know I can get pass the check function inside the for loop by doing something like this:
if (mode == "Horizontal")
{
firstBoundary = cGameBoard.m_nRow;
secondBoundary = cGameBoard.m_nCol;
}
else if (mode == "Vertical")
{
firstBoundary = cGameBoard.m_nCol;
secondBoundary = cGameBoard.m_nRow;
}
void check(string mode)
for (int iii = 1; iii<firstBoundary;; iii++)
{
for (int jjj = 1; jjj<secondBoundary; jjj++)
{
if(Array[jjj][iii]==sign)
{
//do something
}
else
{
//do something else
}
}
}
the problem is the if statement, don't know the best way of swapping the array except doing a function call to do it.
My proposal:
bool if(string mode, int& iii, int &jjj, array,string sign)
{
if(mode=="Horizontal")
return array[iii][jjj]==sign;
else if(mode=="Vertical")
return array[jjj][iii]==sign;
}
And call this function inside if statement
Your solution should work.
void check(bool dir){ // Using a bool will have better performance for checking the mode than string comparisons. Especially since you only have two directions
size_t iEnd = (dir)? cols : rows;
size_t jEnd = (dir)? rows : cols;
for (size_t i = 0; i < iEnd; ++i){
for (size_t j = 0; j < jEnd; ++j){
if(cond(i, j, dir)){
// Do something
} else {
// Do something else
}
}
}
}
bool cond(const size_t& i, const size_t& j, bool dir){
if (dir){
return array[i][j] == sign;
} else {
return array[j][i] == sign;
}
}
You could achieve the same results by using recursion
void check(size_t i, size_t j, bool dir){
if (ROW + COL - (i+j) == 1) return; /* end recursion */
if (i == ROW) return check(0, j+1, dir);
if (j == COL) return check(i+1, 0, dir);
if (array[i][j] == sign){
// Do Something
} else {
// Do Something Else
}
if (dir)
return check(i+1, j, dir);
return check(i, j+1, dir);
}
You're compiler should be able to figure out this only uses tail recursion and you don't have to worry about stack frame limit.

Having trouble compiling my first c++ program

Here is my code:
#include<iostream>
private int chessBoard[8][8];
void printBoard(int board[][])
{
for(int i=0; i<8; i++)
{
for(int j=0; j<8; j++)
{
if(board[i][j])
{
cout<<"Q ";
}
else
{
cout<<"* ";
}
}
cout<<endl;
}
}
//This method will check if any queens are in attacking position to the left of the test queen placement
bool checkSpot(int board[][],int row, int col)
{
bool safe = true;
//checks the current row for queens
for(int i=0; i<col, i++)
{
if(board[row][i])
safe=false;
{
//checks the upper diag
for( int i=row, int j=col; i>0 && j>0; i--, j--)
{
if(board[i][j])
safe=false;
}
//checks lower diag
for(int i = row, int j=col; i<8 && j>0; i--, j++)
{
if(board[i][j])
safe=false;
}
if(safe)
{
return true;
}
else
return false;
}
bool solve(int board[][], int testCol)
{
bool solved = false;
bool safe;
if(testCol==8)
{
solved = true;
return solved;
}
for(int i =0; i>8; i++)
{
// test if the tested column(testCol) and the row(i) are both safe for the queen to be placed at then we can move into placing said queen and more onto the next column for
// more solutions in this same method recursivly
safe = checkSpot(board, i, testCol);
if(safe)
{
//place the queen
board[i][col]=1;
//recursion to go back through this method in the next column
if(solve(board[][], testCol+1)
{
solved = true;
printBoard(board)
return solved;
}
else
{
//if the queen cannot be placed, we have to remove the previous queens and move them until a solution is found.
board[i][testCol]=0;
}
}
}
int main()
{
solve(chessBoard, 0);
}
There errors i continue to get are as follows:
8queens.cpp:3:17: error: variable or field ‘printBoard’ declared void
void printBoard(board[][])
^
8queens.cpp:3:17: error: ‘board’ was not declared in this scope
8queens.cpp:3:23: error: expected primary-expression before ‘]’ token
void printBoard(board[][])
^
8queens.cpp:3:25: error: expected primary-expression before ‘]’ token
void printBoard(board[][])
The logic of this was pretty simple(at least i hope it works well) but i cant even get past the compiler. Can I get a little guidance on this problem?
You were all a huge help, but sadly i found out that I can only use 1d arrays for this problem so I had to start from scratch. Again thank you all for the help, your advice will definitely help me in the future.
Well, there are many errors in your code. Lets look at them.
First of all, remove that private from
private int chessBoard[8][8];
you need to use private only on the members of classes . So change it to
int chessBoard[8][8];
Next, in all your functions, you have something like
void printBoard(int board[][])
^
here, it's wrong
You need to provide the size, you can only skip the first size, all the rest must be provided so better to change it to
void printBoard(int board[][8])
^
it's okay to leave this one
make that change to all of your functions.
You are also missing a few } in some places of your code.
Nearly forgot, you need to either add a
using namespace std;
right after the headers, or use
std::cin
std::cout
and
std::endl
instead of cin , cout and endl .
You also have
for(int i=0; i<col, i++)
^
you need a semicolon here
And also
for( int i=row, int j=col; i>0 && j>0; i--, j--)
^
no need for another int here
just change that to
for( int i=row, j=col; i>0 && j>0; i--, j--)
This compiles. As to what I did, there was a lot and it would take awhile to write each thing down. One major thing to pay attention to is the for loops.
You have:
for( int i=row, int j=col; i>0 && j>0; i--, j--)
{
if(board[i][j])
safe=false;
}
When you want to do a nested for loop, do this:
for (int i = row; i > 0; i--)
{
for (int j = col; j > 0; j--)
{
if (board[i][j])
safe = false;
}
}
Also, pay attention to your brackets {} () as they were inconsistent and some were missing.
For arrays, you must specify at least one dimension when using a 2d array.
You had: int board[][] in various places. You must have: int board[][8] instead.
Also, if you want to use cout, endl, cin, etc... You must have include namespace std; otherwise you will have to use: std::cout, std::endl, std::cin.
But anyway, this should compile now.
#include<iostream>
using namespace std;
int chessBoard[8][8];
void printBoard(int board[][8])
{
for (int i = 0; i<8; i++)
{
for (int j = 0; j<8; j++)
{
if (board[i][j])
{
cout << "Q ";
}
else
{
cout << "* ";
}
}
cout << endl;
}
}
//This method will check if any queens are in attacking position to the left of the test queen placement
bool checkSpot(int board[][8], int row, int col)
{
bool safe = true;
//checks the current row for queens
for (int i = 0; i < col; i++)
{
if (board[row][i])
safe = false;
{
//checks the upper diag
for (int i = row; i > 0; i--)
{
for (int j = col; j > 0; j--)
{
if (board[i][j])
safe = false;
}
}
//checks lower diag
for (int i = row; i < 8; i--)
{
for (int j = col; j > 0; j++)
{
if (board[i][j])
safe = false;
}
}
if (safe)
{
return true;
}
else
return false;
}
}
}
bool solve(int board[][8], int testCol)
{
bool solved = false;
bool safe;
if (testCol == 8)
{
solved = true;
return solved;
}
for (int i = 0; i > 8; i++)
{
// test if the tested column(testCol) and the row(i) are both safe for the queen to be placed at then we can move into placing said queen and more onto the next column for
// more solutions in this same method recursivly
safe = checkSpot(board, i, testCol);
if (safe)
{
//place the queen
board[i][testCol] = 1;
//recursion to go back through this method in the next column
if (solve(board, testCol + 1))
{
solved = true;
printBoard(board);
return solved;
}
else
{
//if the queen cannot be placed, we have to remove the previous queens and move them until a solution is found.
board[i][testCol] = 0;
}
}
}
}
int main()
{
solve(chessBoard, 0);
}

Negamax algorithm

I have worked quite a bit with my tictactoe, but never got it working. Here is what I have so far:
static int evaluate(board b)
{
if (is_win curr_move_noughts)
{
return 1;
}
else if (is_win crosses)
{
return -1;
}
else
{
return 0;
}
}
int evaluateNegamax(board b)
{
if (curr_move_noughts) // Max player
return evaluate(b);
else
return -evaluate(b);
}
tuple<int, move> Search(int depth, board b)
{
board combined(); =b;
int w = 0;
w = Evaluate(b);
int move;
int bestScore = std::numeric_limits<int>::min();
bool bestMove = false;
if(depth == 0) return w;
int x=0, int y=0;
for (int x = 0; x < 9; ++x) {
for (int y = 0; y < 9; ++y) {
while (!occupied(x,y));
make_move(x, y);
score = -Search(depth-1,b); // recursion
unMake(b);
if(score > bestScore) {
bestScore = score;
bestMove = move;
}
}
}
// return the best move
return make_tuple(bestScore, bestMove);
}
Well, obviously " move " needs to be linked to XY coordinate but I don`t kow how.
I have defined make_move like this:
void make_move( size_t row, size_t col, board & b )
{
if (free(row, col))
{
b[pos(row, col)] = true;
last_move_row = row ;
last_move_col = col ;
}
}