I need help to make a Sudoku solver in C++.
Requirements of the program:
Input Sudoku:[Done]
Read Sudoku: [Done]
Validate function: (validates the Sudoku:) [Done]
Display function [done]
solve function [need help]
My plan:
Make a function to validate the sudoku [done]
and assign possibility of 1-9 for every blank colume. and perform a brute-force
method to solve the puzzle. It will call the function validate each time
while doing brute force. It consumes a lot of time and I understood that it is
impossible.
I need a better algorithm for the solve function, please help me.
I have commented some of the code just to analyses the code: Apologize if that is the wrong way.
Here is what I have done so far:
/* Program: To solve a SU-DO-KU:
Date:23-sep-2013 # 5.30:
*/
#include<iostream>
using namespace std;
int su_in[9][9]={
0,0,7 ,0,0,0 ,4,0,6,
8,0,0 ,4,0,0 ,1,7,0,
0,0,0 ,3,0,0 ,9,0,5,
0,0,0 ,7,0,5 ,0,0,8,
0,0,0 ,0,0,0 ,0,0,0,
4,0,0 ,2,0,8 ,0,0,0,
7,0,4 ,0,0,3 ,0,0,0,
0,5,2 ,0,0,1 ,0,0,9,
1,0,8 ,0,0,0 ,6,0,0
};
int su_out[9][9];/*={
5,3,7 ,9,1,2 ,4,8,6,
8,2,9 ,4,5,6 ,1,7,3,
6,4,1 ,3,8,7 ,9,2,5,
9,1,3 ,7,4,5 ,2,6,8,
2,8,6 ,1,3,9 ,7,5,4,
4,7,5 ,2,6,8 ,3,9,1,
7,6,4 ,8,9,3 ,5,1,2,
3,5,2 ,6,7,1 ,8,4,9,
1,9,8 ,5,2,4 ,6,3,7
};*/
struct chance{
int poss[9];
};
int box_validate(int,int,int);
void read(int);
void display(int);
int validate(int);
int solve();
int main()
{
int i,j,row,get_res=2;
enum {input=1,output};
cout<<"enter the sudoku: use 0 if the colum is empty:\n";
// for(i=0; i<9; i++){
// read(i);
// }
cout<<"\n\t\tTHE ENTERED SU-DO-CU IS:\n\n";
display(input);
get_res=validate(input);
if(get_res==0)
cout<<"valid input!\n";
else if(get_res==1)
cout<<"invalid input!\n";
// display(input);
for(i=0; i<9; i++)
for(j=0; j<9; j++)
su_out[i][j]=su_in[i][j];
// display(output);
get_res=validate(output);
if(get_res==0){
cout<<"valid solution!\n"; display(output);}
// else if(get_res==1)
// cout<<"invalid sudoku!\n";
if(solve()==0) display(output);
else cout<<"not solved buddy!!\n";
}
void read(int row) // function to read the SU-DO-CU
{
unsigned num,i;
cout<<"enter the row:'"<<row+1<<"'\n";
for(i=0; i<9; i++)
{
cin>>num;
if(num<0||num>9)
cout<<"error! invalid input: enter a number < or = 9 and > or = 0 \n";
else
su_in[row][i]=num;
}
}
void display(int sudoku) // function to display the SU-DO-CU
{
unsigned i,j;
for(i=0;i<9; i++)
{
if(i%3==0)
cout<<"\t\t-------------------------\n";
cout<<"\t\t";
for(j=0; j<9; j++)
{
if(j%3==0)
cout<<"| ";
// if(su[i][j]==0)
// cout<<"_ ";
// else
if(sudoku==1)
cout<<su_in[i][j]<<" ";
else if(sudoku==2)
cout<<su_out[i][j]<<" ";
if(j==8)
cout<<"|";
}
cout<<"\n";
if(i==8)
cout<<"\t\t-------------------------\n";
}
}
int validate(int sudoku) // function to validate the input SU-DO-CU
{
unsigned i,j,k,n,count=0;
//..........................row validation
for(i=0; i<9; i++)
for(j=0; j<9; j++)
for(k=0;k<9;k++)
{
if(sudoku==1 && k!=j && su_in[i][j]!=0)
{
if(su_in[i][j]==su_in[i][k])
return 1;
}
else if(sudoku==2 && k!=j )
{
if(su_out[i][j]==su_out[i][k])
return 1;
}
}
//..................................colume validation
for(i=0; i<9; i++)
for(j=0; j<9; j++)
for(k=0; k<9; k++)
{
if(sudoku==1 && k!=j && su_in[j][i]!=0)
{
if(su_in[j][i]==su_in[k][i])
return 1;
}
else if(sudoku==2 && k!=i )
{
if(su_out[j][i]==su_out[j][k])
return 1;
}
}
// each box validating.......................
for(i=0; i<=6; i=i+3)
for(j=0; j<=6; j=j+3)
{
if(box_validate(i,j,sudoku)==1)
return 1;
}
// sum validation for output....
if(sudoku==2)
{
for(i=0; i<9; i++)
for(j=0; j<9; j++)
count=count+su_out[i][j];
if(count!=405) return 1;
}
return 0;
}
int box_validate(int i,int j,int sudoku)
{
unsigned k=j,n=i;
int temp_i=i,temp_j=j,temp_k=k, temp_n=n;
for(i=temp_i; i<temp_i+3; i++)
for(j=temp_j; j<temp_j+3; j++)
for(k=temp_k; k<temp_k+3; k++)
{
if(sudoku==1 && k!=j && su_in[i][j]!=0)
{
if(su_in[i][j]==su_in[i][k])
return 1;
for(n=temp_n; n<temp_n+3; n++)
{
if(sudoku==1 && su_in[i][j]!=0)
if(k==j && n==i)
;else
if(su_in[i][j]==su_in[n][k])
return 1;
}
}
if(sudoku==2 && k!=j )
{
if(su_out[i][j]==su_out[i][k])
return 1;
for(n=temp_n; n<temp_n+3; n++)
{
if(sudoku==1 )
if(k==j && n==i)
;else
if(su_out[i][j]==su_out[n][k])
return 1;
}
}
}
return 0;
}
int solve()
{
unsigned i,j,k,m,n,x;
struct chance cell[9][9];
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
for(k=0;k<9; k++)
cell[i][j].poss[k]=k+1;
/*
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
for(k=0;k<9; k++)
{ su_out[i][j]=cell[i][j].poss[k]=k+1;
su_out[i][j]=cell[i][j].poss[k];
for(m=0; m<9; m++)
for(n=0; n<9; n++)
for(x=1; x<=9; x++)
{ if(x!=k+1)
cell[m][n].poss[x]==x;
if(validate(2)==0)
return 0;
}
}*/
for(i=0; i<9; i++)
for(j=0; j<9; j++)
if(su_in[i][j]==0)
while (validate(2)==0)
{
for(k=0;k<9; k++)
{ su_out[i][j]=k+1;
for(m=i+1; m <9 ; m++)
for(n=0; n <9 ; n++)
for(x=1; x<=9; x++)
{ su_out[m][n]=x;
if(validate(2)==0)
return 0;
}
}
}
}
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
#define UNASSIGNED 0
#define N 9
bool FindUnassignedLocation(int grid[N][N], int &row, int &col);
bool isSafe(int grid[N][N], int row, int col, int num);
/* assign values to all unassigned locations for Sudoku solution
*/
bool SolveSudoku(int grid[N][N])
{
int row, col;
if (!FindUnassignedLocation(grid, row, col))
return true;
for (int num = 1; num <= 9; num++)
{
if (isSafe(grid, row, col, num))
{
grid[row][col] = num;
if (SolveSudoku(grid))
return true;
grid[row][col] = UNASSIGNED;
}
}
return false;
}
/* Searches the grid to find an entry that is still unassigned. */
bool FindUnassignedLocation(int grid[N][N], int &row, int &col)
{
for (row = 0; row < N; row++)
for (col = 0; col < N; col++)
if (grid[row][col] == UNASSIGNED)
return true;
return false;
}
/* Returns whether any assigned entry n the specified row matches
the given number. */
bool UsedInRow(int grid[N][N], int row, int num)
{
for (int col = 0; col < N; col++)
if (grid[row][col] == num)
return true;
return false;
}
/* Returns whether any assigned entry in the specified column matches
the given number. */
bool UsedInCol(int grid[N][N], int col, int num)
{
for (int row = 0; row < N; row++)
if (grid[row][col] == num)
return true;
return false;
}
/* Returns whether any assigned entry within the specified 3x3 box matches
the given number. */
bool UsedInBox(int grid[N][N], int boxStartRow, int boxStartCol, int num)
{
for (int row = 0; row < 3; row++)
for (int col = 0; col < 3; col++)
if (grid[row+boxStartRow][col+boxStartCol] == num)
return true;
return false;
}
/* Returns whether it will be legal to assign num to the given row,col location.
*/
bool isSafe(int grid[N][N], int row, int col, int num)
{
return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) &&
!UsedInBox(grid, row - row % 3 , col - col % 3, num);
}
void printGrid(int grid[N][N])
{
for (int row = 0; row < N; row++)
{
for (int col = 0; col < N; col++)
cout<<grid[row][col]<<" ";
cout<<endl;
}
}
int main()
{
int grid[N][N] = {{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0}};
if (SolveSudoku(grid) == true)
printGrid(grid);
else
cout<<"No solution exists"<<endl;
return 0;
}
Here's my code:
I think it's the best.
/*
* File: Sudoku-Solver.cc
*
* Created On: 12, April 2016
* Author: Shlomo Gottlieb
*
* Description: This program holds A sudoku board (size: 9*9),
* it allows the user to input values that he choices
* and finds the first rational solution.
* The program also prints the sudoku whether A solution
* was found or not.
*
*/
//========= Includes =========//
#include <iostream>
//========= Using ==========//
using namespace std;
//========= Constants =========//
const int N = 3; // The size of 1 square in the sudoku.
const int EMPTY = 0; // A sign for an empty cell.
const int STOP_INPUT = -1; // A sign for stop get input.
//====== Function Declaration ======//
void input_sud(int sud[][N*N]);
bool fill_sud(int sud[][N*N], int row, int col);
void print_sud(const int sud[][N*N]);
bool is_legal(const int sud[][N*N], int row, int col, int val);
bool is_row_ok(const int row[], int col, int val);
bool is_col_ok(const int sud[][N*N], int row, int col, int val);
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val);
//========== Main ===========//
int main()
{
int sud[N*N][N*N] = { { EMPTY } }; // The sudoku board.
input_sud(sud);
fill_sud(sud, 0, 0);
print_sud(sud);
return 0;
}
//======== Input Sudoku ========//
// Gets the input for the sudoku,
// 0 means an empty cell.
void input_sud(int sud[][N*N])
{
for(int i = 0; i < N*N; i++)
for(int j = 0; j < N*N; j++)
cin >> sud[i][j];
}
//======== Fill Sudoku =========//
// Tries to fill-in the given sudoku board
// according to the sudoku rules.
// Returns whether it was possible to solve it or not.
bool fill_sud(int sud[][N*N], int row, int col)
{
// Points to the row number of the next cell.
int next_row = (col == N*N - 1) ? row + 1 : row;
// Points to the column number of the next cell.
int next_col = (col + 1) % (N*N);
// If we get here, it means we succeed to solve the sudoku.
if(row == N*N)
return true;
// Checks if we are allowed to change the value of the current cell.
// If we're not, then we're moving to the next one.
if(sud[row][col] != EMPTY)
return fill_sud(sud, next_row, next_col);
// We're about to try and find the legal and appropriate value
// to put in the current cell.
for(int value = 1; value <= N*N; value++)
{
sud[row][col] = value;
// Checks if 'value' can stay in the current cell,
// and returns true if it does.
if(is_legal(sud, row, col, value) && fill_sud(sud, next_row, next_col))
return true;
// Trial failed!
sud[row][col] = EMPTY;
}
// None of the values solved the sudoku.
return false;
}
//======== Print Sudoku ========//
// Prints the sudoku Graphically.
void print_sud(const int sud[][N*N])
{
for(int i = 0; i < N*N; i++)
{
for(int j = 0; j < N*N; j++)
cout << sud[i][j] << ' ';
cout << endl;
}
}
//========== Is Legal ==========//
// Checks and returns whether it's legal
// to put 'val' in A specific cell.
bool is_legal(const int sud[][N*N], int row, int col, int val)
{
return (is_row_ok(sud[row], col, val) &&
is_col_ok(sud, row, col, val) &&
is_sqr_ok(sud, row, col, val));
}
//========= Is Row OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific row.
bool is_row_ok(const int row[], int col, int val)
{
for(int i = 0; i < N*N; i++)
if(i != col && row[i] == val)
return false; // Found the same value again!
return true;
}
//========= Is Column OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific column.
bool is_col_ok(const int sud[][N*N], int row, int col, int val)
{
for(int i = 0; i < N*N; i++)
if(i != row && sud[i][col] == val)
return false; // Found the same value again!
return true;
}
//========= Is Square OK =========//
// Checks and returns whether it's legal
// to put 'val' in A specific square.
bool is_sqr_ok(const int sud[][N*N], int row, int col, int val)
{
int row_corner = (row / N) * N;
// Holds the row number of the current square corner cell.
int col_corner = (col / N) * N;
// Holds the column number of the current square corner cell.
for(int i = row_corner; i < (row_corner + N); i++)
for(int j = col_corner; j < (col_corner + N); j++)
if((i != row || j != col) && sud[i][j] == val)
return false; // Found the same value again!
return true;
}
//here's a pseudo sudoku solver:
#include <iostream>
#include <cmath>
#include "time.h"
//for(int i=0; i< ++i){}
using namespace std;
int main(){
int a[9][9]={{0,7,0,0,2,0,1,0,0},
{6,0,3,0,0,0,0,0,0},
{2,0,0,3,0,0,5,0,0},
{0,0,0,0,3,0,0,6,0},
{0,6,4,7,0,0,0,8,0},
{0,5,0,0,9,0,0,4,0},
/*54*/ {0,4,0,0,7,0,9,0,0},
{0,2,0,0,0,8,0,5,0},
{0,0,0,0,0,0,0,0,0}};/*this is the grid. I need to use two so that I can use one as a constant reference*/
int a2[9][9]={{0,7,0,0,2,0,1,0,0},
{6,0,3,0,0,0,0,0,0},
{2,0,0,3,0,0,5,0,0},
{0,0,0,0,3,0,0,6,0},
{0,6,4,7,0,0,0,8,0},
{0,5,0,0,9,0,0,4,0},
{0,4,0,0,7,0,9,0,0},
{0,2,0,0,0,8,0,5,0},
{0,0,0,0,0,0,0,0,0}};
int x=0,y=0,z=0;
int oo=0,o=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)/*this is the double for loop. to keep track of the cells*/
{
for(int j=0; j<9; ++j)
{
if(!a2[i][j])
{a://label that if something doesn't work, to restart here.
++a[i][j];//increment the number in the cell by 1.
if(a[i][j]>9)/*if no valid number is found/the number is out of range, execute the if statement. **This is the backtracking algorithm.***/
{
a[i][j]=0;//erase the invalid number.
--j;if(j<0){--i;j=8;} /*if j equals < 0, j is reset to 8, as the first 9 numbers are easy to find, and if j needs to be reset, there will always be a number in the j equals 8 cell. The "i" will never be less than zero, if it is a valid puzzle, so the j=8 will only happen after i is > 0.*/
while(a2[i][j]){--j;if(j<0){--i;j=8;}}/*if there was a number present from the beginning, skip it until a variable cell space is found.*/
goto a;//jump to a: and increment the current number in the cell by 1.
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}/*locate the 3X9 grid j is in.*/
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}/*locate the 9X3 grid i is in.*/
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)/*intersect the 3X9 and 9X3 grids to create a searchable 3X3 grid.*/
{
for(int p=o; p<oo; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){x=0;goto a;}}/*if the number is not valid, go to a: and increment the number in the cell by 1.*/
}
}
x=0;
for(int n=0; n<9; ++n)
{
if(a[i][j]==a[i][n]){++y; if(y>1){y=0;goto a;}}/*if no valid number is found, goto a: and increment the number in the cell by 1.*/
}y=0;
for(int m=0; m<9; ++m)
{
if(a[i][j]==a[m][j]){++y; if(y>1){y=0;goto a;}}//""
} y=0;
}
}
}
for(int i=0; i<9; ++i)//print the completed puzzle.
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;//print on the next line after 9 digits are printed.
}
return 0;
}
//if no valid puzzle is found, the screen hangs. - Harjinder
/*random sudokus' can be generated and solved in one program by copying the following code into an editor. hit enter to generate and solve a new puzzle:
//the following works the same way as above except that it is 2 solvers in a continuous while loop
//the first solver, to generate the random puzzle:
#include <iostream>
using namespace std;
int main(){
while(1){
int a[9][9]={0}, a2[9][9]={0};
int w=0, x=0,y=0,z=0, yy=0, oo=0,o=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
if(!a2[i][j])
{srand(time(0));if(w<5){++w;a[i][j]=rand()%9;}a:++a[i][j];//generate a random number from 0 to 9 and and then increment by 1.
if(a[i][j]>9)
{
a[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a2[i][j]){--j;if(j<0){--i;j=8;}}
goto a;
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)
{
for(int p=o; p<oo; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){x=0;goto a;}}
}}
x=0;
for(int n=0; n<9; ++n)
{
if(a[i][j]==a[i][n]){++y; if(y>1){y=0;goto a;}}
}y=0;
for(int m=0; m<9; ++m)
{
if(a[i][j]==a[m][j]){++y; if(y>1){y=0;goto a;}}
} y=0;}//if
}
}
//the second part below is to add zeros' to the puzzle, and copy the puzzle into the second solver arrays.
int n=40;//adjusts the amount of empty spaces. works only if landed on non-zero, or else the zero will be counted.
x=0;int xx=0;
o=0;int pp=0,ppp=0;
while(o<n)
{
pp=rand()%9;
ppp=rand()%9;
a[pp][ppp]=0;
pp=rand()%9;
ppp=rand()%9;
a[ppp][pp]=0;
++o;
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
x=0,xx=0;
cout<<endl<<endl;
int a5[9][9]={0}, a6[9][9]={0};x=-1;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
++x;
a5[i][j]=a[i][j];//copy first puzzle with added zeros into the new array.
}
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
a6[i][j]=a5[i][j];//copy the updated puzzle with zeros, into the constant reference array.
}
}
x=0;
////////////////////////////////////////////////////////////////////////
//second solver to solve the zero updated array:
cout<<endl<<endl;
o=0;
y=0,z=0;
oo=0,ooo=0,oooo=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
if(!a6[i][j])
{c5:
++a5[i][j];
if(a5[i][j]>9)
{
a5[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a6[i][j]){--j;if(j<0){--i;j=8;}}
goto c5;
}
if(j<3){o=0;oo=3;}if(j>2 && j<6){o=3;oo=6;}
if(j>5){o=6;oo=9;}
if(i<3){ooo=0;oooo=3;}if(i>2 && i<6){ooo=3;oooo=6;}
if(i>5){ooo=6;oooo=9;}
for(int u=ooo; u<oooo; ++u)
{
for(int p=o; p<oo; ++p)
{
if(a5[u][p]==a5[i][j]){++x;if(x>1){x=0;goto c5;}}
}}
x=0;
for(int n=0; n<9; ++n)
{
if(a5[i][j]==a5[i][n]){++y; if(y>1){y=0;goto c5;}}
}y=0;
for(int m=0; m<9; ++m)
{
if(a5[i][j]==a5[m][j]){++y; if(y>1){y=0;goto c5;}}
} y=0;} }
}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a5[i][j]<<" ";
}
cout<<endl;
}
cout<<endl;
system("pause");//hit enter to load a new puzzle
}
return 0;
} */
The answer given above is similar to what a lot of people have posted at several websites like https://www.geeksforgeeks.org/sudoku-backtracking-7/. TBH, those solutions are not intuitive to me when they don't initialize row and col and call it in the FindUnassignedLocation function. I wanted to give it a shot myself with slight help from another answer I found on LeetCode. If it helps anyone, here you go.
// https://www.pramp.com/challenge/O5PGrqGEyKtq9wpgw6XP
#include <iostream>
#include <vector>
using namespace std;
// Print the sudoku
void print(vector<vector<char>> board){
for(int i = 0; i < board.size(); i++){
for(int j = 0; j < board[i].size(); j++){
cout << board[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
// Check if sudoku is all filled up
bool checkIfFilled(vector<vector<char>> board){
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
if(board[i][j] == '.')
return false;
}
}
return true;
}
// Check if a given number can be inserted at a given position
bool checkIfInsertOkay(vector<vector<char>> board, int x, int y, char num){
// Check row if num already exists
for(int j = 0; j < 9; j++){
if(board[x][j] == num)
return false;
}
// Check column if num already exists
for(int i = 0; i < 9; i++){
if(board[i][y] == num)
return false;
}
// Check 3x3 gird if num already exists
// Find the corners
// Find i
if(x < 3)
x = 0;
else if(x < 6)
x = 3;
else
x = 6;
// Find j
if(y < 3)
y = 0;
else if(y < 6)
y = 3;
else
y = 6;
// Check the 3x3 box
for(int i = x; i < x+3; i++){
for(int j = y; j < y+3; j++){
if(board[i][j] == num)
return false;
}
}
return true;
}
// Helper function because of const issues
bool sudokuSolveHelper(vector<vector<char>> &board){
// Base condition - if sudoku gets completely filled
if(checkIfFilled(board))
return true;
// Iterate through the sudoku
for(int i = 0; i < 9; i++){
for(int j = 0; j < 9; j++){
// If empty space
if(board[i][j] == '.'){
for(int k = 1; k <= 9; k++){
// Check if char(k) can be inserted at this empty location
char ch = '0' + k;
if(checkIfInsertOkay(board, i, j, ch)){
// Put k in this empty location and check
board[i][j] = ch;
// Check if done
bool flag = sudokuSolveHelper(board);
if(flag)
return true;
else
// Else, backtrack by making it empty again
board[i][j] = '.';
}
}
return false;
}
}
}
return true;
}
// Return true if a correct sudoku can be formed
// Apply backtracking
// Time complexity = O(9^empty spaces)
bool sudokuSolve(vector<vector<char>> &board){
return sudokuSolveHelper(board);
}
int main() {
vector<vector<char>> board = {
{'.','.','.','7','.','.','3','.','1'},
{'3','.','.','9','.','.','.','.','.'},
{'.','4','.','3','1','.','2','.','.'},
{'.','6','.','4','.','.','5','.','.'},
{'.','.','.','.','.','.','.','.','.'},
{'.','.','1','.','.','8','.','4','.'},
{'.','.','6','.','2','1','.','5','.'},
{'.','.','.','.','.','9','.','.','8'},
{'8','.','5','.','.','4','.','.','.'}
};
print(board);
bool flag = sudokuSolve(board);
if(flag){
cout << "A solution exists as below\n";
print(board);
}
else
cout << "No solution exists!\n";
return 0;
}
//the following works like the one above accept there is a while loop instead of goto statements:
#include <iostream>
#include <cmath>
#include "time.h"
//for(int i=0; i< ++i){}
using namespace std;
int main(){
int a[9][9]={{2,0,0,0,0,0,0,0,1},
{0,0,0,9,0,6,0,0,0},
{0,0,0,8,0,1,7,2,0},
{9,0,0,3,0,0,0,0,0},
{0,0,8,0,0,0,2,0,4},
{0,0,0,0,0,0,0,1,3},
/*54*/ {1,0,3,0,0,5,0,0,9},
{0,0,0,0,0,0,0,0,0},
{0,4,6,2,0,0,0,0,0}};
int a2[9][9]={{2,0,0,0,0,0,0,0,1},
{0,0,0,9,0,6,0,0,0},
{0,0,0,8,0,1,7,2,0},
{9,0,0,3,0,0,0,0,0},
{0,0,8,0,0,0,2,0,4},
{0,0,0,0,0,0,0,1,3},
{1,0,3,0,0,5,0,0,9},
{0,0,0,0,0,0,0,0,0},
{0,4,6,2,0,0,0,0,0}};
int x=0,y=0,z=0;
int colPlusThree=0,col=0,row=0,rowPlusThree=0;
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{z=0;
if(!a2[i][j])
{while(z==0){ //the master while loop. loops until a valid number is found.
++a[i][j];
if(a[i][j]>9)
{
a[i][j]=0;
--j;if(j<0){--i;j=8;}
while(a2[i][j]){--j;if(j<0){--i;j=8;}}
++a[i][j];if(a[i][j]>9){--j;}
}
if(j<3){col=0;colPlusThree=3;}if(j>2 && j<6){col=3;colPlusThree=6;}
if(j>5){col=6;colPlusThree=9;}
if(i<3){row=0;rowPlusThree=3;}if(i>2 && i<6){row=3;rowPlusThree=6;}
if(i>5){row=6;rowPlusThree=9;}
for(int u=row; u<rowPlusThree; ++u)
{
for(int p=col; p<colPlusThree; ++p)
{
if(a[u][p]==a[i][j]){++x;if(x>1){u=rowPlusThree;break;}}
}}if(x<2){z=1;}else{z=0;}x=0;
for(int n=0; n<9; ++n)
{
if(z==0){y=2;break;}
if(a[i][j]==a[i][n]){++y; if(y>1){break;}}
}if(y<2){z=1;}else{z=0;}y=0;
for(int m=0; m<9; ++m)
{
if(z==0){y=2;break;}
if(a[i][j]==a[m][j]){++y; if(y>1){break;}}
} if(y<2){z=1;}else{z=0;}y=0;}}}}
for(int i=0; i<9; ++i)
{
for(int j=0; j<9; ++j)
{
cout<<a[i][j]<<" ";
}
cout<<endl;
}
return 0;
}// - Harjinder
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I am writing a C++ code for a Sudoku solver.
The code must work for a 9x9, 16x16 and 25x25 grid. My code only works for a 9x9 grid. I am not sure why. May someone please help me. I think I need to make the 16x16 and 25x25 codes work faster somehow. How do I do this?
#include <iostream>
#include <vector>
#include <string>
#include <cmath>
using namespace std;
vector<int> tokenize(string s, string del);
void readAPuzzle(vector<vector<int>> &grid);
void printGrid(vector<vector<int>> grid);
bool isValid(int i, int j, vector<vector<int>> grid);
bool isValid(vector<vector<int>> grid);
bool search(vector<vector<int>> &grid);
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList);
int main()
{
// Read a Sudoku puzzle
vector<vector<int>> puzzle;
readAPuzzle(puzzle);
if (!isValid(puzzle))
cout << "Invalid input" << endl;
else if (search(puzzle)){
printGrid(puzzle);
}
else
cout << "No solution" << endl;
return 0;
}
vector<int> tokenize(string s, string del)
{
vector<int> row;
int start = 0;
int end = s.find(del);
while (end != -1) {
row.push_back(stoi( s.substr(start, end - start)));
start = end + del.size();
end = s.find(del, start);
}
row.push_back(stoi( s.substr(start, end - start)));
return row;
}
void readAPuzzle(vector<vector<int>> &grid){
string line;
getline(cin, line);
vector<int> firstRow = tokenize(line, " ");
grid.push_back(firstRow);
for(int i = 0; i < firstRow.size()-1; i++){
getline(cin, line);
vector<int> row = tokenize(line, " ");
grid.push_back(row);
}
}
/** Obtain a list of free cells from the puzzle */
int getFreeCellList(vector<vector<int>> grid, vector<pair<int, int>> &freeCellList)
{
// 81 is the maximum number of free cells
int numberOfFreeCells = 0;
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] == 0)
{
freeCellList[numberOfFreeCells].first = i;
freeCellList[numberOfFreeCells].second = j;
numberOfFreeCells++;
}
return numberOfFreeCells;
}
/** Print the values in the grid */
void printGrid(vector<vector<int>> grid)
{
for (int i = 0; i < grid.size(); i++)
{
for (int j = 0; j < grid.size(); j++)
cout << grid[i][j] << " ";
cout << endl;
}
}
/** Search for a solution */
bool search(vector<vector<int>> &grid)
{
int k = 0; // Start from the first free cell
bool found = false; // Solution found?
const int n = grid.size();
vector<pair<int, int>> freeCellList(n*n);
int numberOfFreeCells = getFreeCellList(grid, freeCellList);
while (!found)
{
int i = freeCellList[k].first;
int j = freeCellList[k].second;
if (grid[i][j] == 0)
grid[i][j] = 1; // Start with 1
if (isValid(i, j, grid))
{
if (k + 1 == numberOfFreeCells)
{ // No more free cells
found = true; // A solution is found
}
else
{ // Move to the next free cell
k++;
}
}
else if (grid[i][j] < grid.size())
{
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
else
{ // grid[i][j] is 9, backtrack
while (grid[i][j] == grid.size())
{
grid[i][j] = 0; // Reset to free cell
if (k == 0)
{
return false; // No possible value
}
k--; // Backtrack
i = freeCellList[k].first;
j = freeCellList[k].second;
}
grid[i][j] = grid[i][j] + 1; // Check the next possible value
}
}
return true; // A solution is found
}
/** Check whether grid[i][j] is valid in the grid */
bool isValid(int i, int j, vector<vector<int>> grid)
{
// Check whether grid[i][j] is valid at the i's row
for (int column = 0; column < grid.size(); column++)
if (column != j && grid[i][column] == grid[i][j])
return false;
// Check whether grid[i][j] is valid at the j's column
for (int row = 0; row < grid.size(); row++)
if (row != i && grid[row][j] == grid[i][j])
return false;
int n = sqrt(grid.size());
// Check whether grid[i][j] is valid in the 3 by 3 box
for (int row = (i / n) * n; row < (i / n) * n + n; row++)
for (int col = (j / n) * n; col < (j / n) * n + n; col++)
if (row != i && col != j && grid[row][col] == grid[i][j])
return false;
return true; // The current value at grid[i][j] is valid
}
/** Check whether the fixed cells are valid in the grid */
bool isValid(vector<vector<int>> grid)
{
// Check for duplicate numbers
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if (grid[i][j] != 0)
if (!isValid(i, j, grid))
return false;
// Check whether numbers are in the range
for (int i = 0; i < grid.size(); i++)
for (int j = 0; j < grid.size(); j++)
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
return true; // The fixed cells are valid
}
This is the code I have written so far.
Thank you.
In bool isValid(vector<vector<int>>) you have
if ((grid[i][j] < 0) || (grid[i][j] > 9))
return false;
ie a grid with a number > 9 is never considered valid. I cannot tell if there are other errors, but when you only allow numbers in [0,9] it cannot work for 16x16 or 25x25 sized grids.
You are passing the grid by value to some of the functions. You should pass them as const reference instead to avoid unnecessary copies.
class matrix
{
public:
int nrow;
int ncol;
double **m;
matrix(int r, int c)
{
nrow = r; ncol = c;
m = (double**)malloc(nrow*sizeof(double*));
for(int i=0; i<nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<nrow; i++)
for(int j=0; j<ncol; j++)
m[i][j] = 0;
}
~matrix()
{
for(int i=0; i<nrow; i++)
{
printf("destructor loop: %d\n", i); fflush(stdout);
free(m[i]);
}
free(m);
}
matrix(const matrix& that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void operator=(const matrix &that)
{
this->nrow = that.nrow;
this->ncol = that.ncol;
for(int i=0; i<nrow; i++) // clear current m
free(m[i]);
free(m);
this->m = (double**)malloc(nrow*sizeof(double*)); // dynamic mem allocation
for(int i=0; i<this->nrow; i++)
m[i] = (double*)malloc(ncol*sizeof(double));
for(int i=0; i<that.nrow; i++)
for(int j=0; j<that.ncol; j++)
this->m[i][j] = that.m[i][j];
}
void show()
{
printf(" Marix:\n");
for(int i=0; i<nrow; i++)
{
printf(" ");
for(int j=0; j<ncol; j++)
{
if(m[i][j] >= 0) printf(" ");
printf("%.6lf ", m[i][j]);
}
printf("\n");
}
printf("\n");
}
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
double det()
{
if(nrow != ncol)
{
printf("non-square matrix: (%d, %d)\n\n", nrow, ncol);
exit(1);
}
if(nrow == 1) return m[0][0];
if(nrow == 2)
{
double ans = m[0][0]*m[1][1] - m[1][0]*m[0][1];
return ans;
}
double ans = 0;
int sign = 1;
for(int i=0; i<nrow; i++)
{
printf("det[size:%d, %d] loop row: %d\n", nrow, ncol, i); fflush(stdout);
matrix a(2, 2);
a = cofactor(i, 0);
ans += (sign*a.det());
sign = sign*(-1);
}
return ans;
}
};
int main()
{
matrix c(3, 3);
c.m[0][0] = 2; c.m[0][1] = -3; c.m[0][2] = 1;
c.m[1][0] = 2; c.m[1][1] = 0; c.m[1][2] = -3;
c.m[2][0] = 1; c.m[2][1] = 4; c.m[2][2] = 5;
c.show();
printf("determinant: %lf\n", c.det());
return 0;
}
A segmentation fault occurs when calling the det function for even 3x3 matrices.
i do not have experience with sophisticated debuggers but using printf statements it looks like the runtime error occurs during an iteration of the loop in the destructor. also i have tried using vector< vector< double >> instead of double**. i assumed it would not need a destructor in that case. then it is giving me a "double free error". i understand when it occurs but cannot find the error in my code. i have also tried calculating the cofactor inline instead of calling a function but it does not help.
int x = 0, y = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
The logic for incrementing y is broken here. Perform a simple mental experiment. If the original matrixes are 3x3, and they are being reduced here to a 2x2 matrix, your ans, then you expect each value in ans to be initialized here, and
ans.m[x][y] = m[i][j];
y++;
will get executed four times. Since y is initially set to 0 and never gets reset to 0, the value of y used in this assignment will range from 0 to 3, so, at some point, this will attempt to assign something to ans.m[x][3], which, of course, doesn't exist, and hillarity ensues.
It seems that the obvious intent here is to reset
y=0;
As the very first order of business in the outer for loop, instead of just once, at the very beginning.
The problem is in the cofactor function. You have declared int x = 0, y = 0 outside of the loops. In the case of x (the row of the cofactor matrix, ans) its fine. But we want the y to be 0 everytime we start with a new row, i.e. y should be in sync with j, skipping when j==c.
What is happening is you skip row 0, since i==r, then in the next row (i=1), you iterate over the columns, skip col 0, since j==c, then go over col 1, col 2, so the code that got executed was
ans.m[0][0] = m[1][1], y++,
ans.m[0][1] = m.[1][2], y++, then we are done with the columns.
We increment x (x=1 now), we go to the next row, row 2 (i=2), but y=2, and not reset. So the next row executes this code:
ans.m[1][2] = m[2][1] (skipping col 0),
which is out of bounds for ans, since ans has ncols-1 = 2 columns.
This results in an error when the destructor for ans is called at the end of cofactor function. I fixed the cofactor code, and this results in no errors when calling det for 3*3 matrices.
matrix cofactor(int r, int c) // returns cofactor of a[r][c]
{
printf("cofactor: size:(%d, %d) element:(%d, %d)\n", nrow, ncol, r, c); fflush(stdout);
matrix ans(nrow-1, ncol-1);
int x = 0;
for(int i=0; i<nrow; i++)
{
if(i == r) continue;
int y = 0;
for(int j=0; j<ncol; j++)
{
if(j == c) continue;
ans.m[x][y] = m[i][j];
y++;
}
x++;
}
return ans;
}
To debug, I would recommend gdb. You can use onlinegdb.com paste your code there, click debug. Then set breakpoints by break <line_number>, then run, n for next instruction, s for step into function. You can search to find out more.
For the following code, how can I find [A^-1] using pointers(equation for [A^-1]= 1/ det (A)? I am not sure whether pointers are used in the arithmetic or if they are used to call a value. Explaining what a pointer would be nice as I'm not exactly sure what they even do. I have most of the code written, except for this one part, so any help is much appreciated. Thanks in advance.
#include <iostream>
#include <cmath>
#include <string>
#include <fstream>
#include <ctime>
#include <cstdlib>
#include <bits/stdc++.h>
#define N 3
using namespace std;
template<class T>
void display(T A[N][N])
{
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
cout << A[i][j] << "\t\t";
cout << endl;
}
}
template<class T>
void display(T A[N])
{
for (int i=0; i<N; i++)
{
cout << A[i]<< "\n";
}
}
void getCofactor(int A[N][N], int temp[N][N], int p, int q, int n)
{
int i = 0, j = 0;
for (int row = 0; row < n; row++)
{
for (int col = 0; col < n; col++)
{
if (row != p && col != q)
{
temp[i][j++] = A[row][col];
if (j == n - 1)
{
j = 0;
i++;
}
}
}
}
}
int determinant(int A[N][N], int n)
{
int D = 0;
if (n == 1)
return A[0][0];
int temp[N][N];
int sign = 1;
for (int f = 0; f < n; f++)
{
getCofactor(A, temp, 0, f, n);
D += sign * A[0][f] * determinant(temp, n - 1);
sign = -sign;
}
return D;
}
void adjoint(int A[N][N],int adj[N][N])
{
if (N == 1)
{
adj[0][0] = 1;
return;
}
int sign = 1, temp[N][N];
for (int i=0; i<N; i++)
{
for (int j=0; j<N; j++)
{
getCofactor(A, temp, i, j, N);
sign = ((i+j)%2==0)? 1: -1;
adj[j][i] = (sign)*(determinant(temp, N-1));
}
}
}
bool inverse(int A[N][N]){
int det = determinant(A, N);
if (det == 0){
cout << "Singular matrix, can't find its inverse";
return false;
}
return true;
}
void computeInverse(int A[N][N], float inverse[N][N]){
int det = determinant(A, N);
int adj[N][N];
adjoint(A, adj);
for (int i=0; i<N; i++)
for (int j=0; j<N; j++)
inverse[i][j] = adj[i][j]/float(det);
cout<<"\nThe Inverse of the Matrix A is:"<<endl;
display(inverse);
}
int main()
{
system("cls");
int A[N][N] = {{-1, 4, -2}, {-3, -2, +1}, {+2, -5, +3}};
char X[N];
int B[N];
float inv[N][N];
cout<<"\nEnter a 3*3 Matrix A"<<endl;
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
cin>>A[i][j];
}
}
cout<<"\nEnter variables x, y, z for Matrix X"<<endl;
for(int i=0;i<N;i++){
cin>>X[i];
}
if (X[0] == 'x' && X[1] == 'y' && X[2] == 'z')
cout<<"\nMatrix X is Valid"<<endl;
else{
cout<<"\nMatrix X is Invalid"<<endl;
return -1;
}
cout<<"\nEnter values for Matrix B"<<endl;
for(int i=0; i<N; i++)
cin>>B[i];
cout<<"\nMatrix A is:------->\n";
display(A);
cout<<"\nMatrix X is:------->\n";
display(X);
cout<<"\nMatrix B is:------->\n";
display(B);
bool isInverseExist = inverse(A);
if (isInverseExist)
computeInverse(A, inv);
return 0;
}
Okay, Here is a simple pointer example using a char array. This can work with other data types as well. Don't remember where I read it; Think of a pointer as an empty bottle.
lets break this down in English first then I'll share a simple example that can be compiled. Imagine that you have 10 m&m's sitting in front of you on a table.
These m&m's represent a character array that we will call char mm[10]; Assume that this array is filled with chars that represent the color of all 10 of the m&m's
Now, we don't want to leave our candy's on the table all day so we will store all ten of the m&m's in a special jar specifically made for the m&m's. this jar will be called char* mm_ptr;
So now we are left with a table of m&m's and a jar sitting next to the pile. The next step is to fill the jar with the m&m's and you do it like this: mm_ptr = mm;
You now have a "jar full of m&m's". This allows you to access the m&m's directly from the jar!
Here is a Working example of of putting m&m's into a jar:
#include <iostream>
//using namespace std;
int main(){//The main function is our table
char mm[10]; //Our pile of m&m's
for(int i=0; i<10; i++){
if(i < 5){
mm[i] = 'b'; //Lets say that half of the m&m's are blue
}else{
mm[i] = 'r'; //and that the other half is red
}
}
char* mm_ptr; //This is our bottle that we will
//use to store our m&m's
mm_ptr = mm; //this is us storing the m&m's in the jar!
for(int i=0; i<10; i++){//Lets dump those candies back onto the table!
std::cout<<mm_ptr[i]<<std::endl;
}
return 0;
}
A correctly initialized pointer will work almost exactly like a normal array
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
// Functions used in the program.
bool uniqueCheck(int arr[][3], int num);
bool magicSquare(int arr[][3]);
int rTotal(int arr[][3], int row);
int cTotal(int arr[][3], int col);
int dTotal(int arr[][3], bool left);
void display(int arr[][3]);
int main()
{
int arr[3][3]; //makes the array 3x3 makes it into the square
int test[3][3] = {2, 7, 6, 9, 5, 1 , 4 , 3 ,8}; //numbers from 1-9 in order of magic square.
while (1)
{
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
arr[i][j] = 0;// nested for loop the i is for rows and the j is for columns
srand((unsigned)time(NULL));// generates random numbers
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
while (1)
{
int num = (rand() % 9) + 1; // Random function will spit out random numbers from 1-9.
if (uniqueCheck(arr, num))
{
arr[i][j] = num;
break;
}
}
}
}
display(arr);
if (magicSquare(arr))//If the magic square array is an actual magic square than this outputs
{
cout << "This is the Magic Square !" << endl;
break;
}
else //if not than it'll keep looping this until the top one is displayed
cout << "This is Not the Magic Square !" << endl;
}
return 0;
}
// check if the random number generated is a unique number
bool uniqueCheck(int arr[][3], int num)
{
for (int k = 0; k < 3; k++)
for (int i = 0; i < 3; i++)
if (arr[k][i] == num)
return false;
return true;
}
bool magicSquare(int arr[][3]) //This will check if the number presented (randomly) correspond with the magic square numbers.
{
int sum = dTotal(arr, true); // Will check the sum of the diagonal.
if (sum != dTotal(arr, false))
return false;
for (int i = 0; i < 3; i++)
{
if (sum != rTotal(arr, i)) // This will check each row and see if its true or false.
return false;
if (sum != cTotal(arr, i)) // This will check each column and see if its true or false.
return false;
}
return true;
}
int rTotal(int arr[][3], int row) // This will calculate the sum of one row at a time.
{
int sum = 0;
for (int i = 0; i < 3; i++)
sum += arr[row][i];
return sum;
}
int cTotal(int arr[][3], int col) // This will calculate the sum of one column at a time.
{
int sum = 0;
for (int i = 0; i < 3; i++)
sum += arr[i][col];
return sum;
}
int dTotal(int arr[][3], bool left) // This will calculate the sum of diagonal. if the left is true, it will calculate from the left to the right diagonal. If false it will calculate from the right to the left diagonal.
{
int sum = 0;
if (left == true)
{
for (int i = 0; i < 3; i++)
sum += arr[i][i];
return sum;
}
for (int i = 0; i < 3; i++)
sum += arr[i][3 - i - 1];
return sum;
}
void display(int arr[][3]) //This will display the array.
{
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
cout << arr[i][j] << " ";
cout << endl;
}
cout << endl;
}
This is my code. This calculates a magic square. The only thing I cannot get is my numbers are suppose to switch each time it loops but it shows the same number each time it loops which basically make it an infinite loop...what I'm asking for is help on getting the numbers to change each time it loops. Thank you very much in advance.
When writing code, you should develop new functionality in isolation, before integrating it with other code.
When you were working with the random number generator, you should have noticed that this:
srand((unsigned)time(NULL));// generates random numbers
resets the random number generator. And since you do this in every pass through the main loop, you get the same "random" numbers every time.
Move that line up, outside the loop.
I am trying to solve http://www.spoj.com/problems/BOTTOM/
Here are the steps I am following:
1) Find the strongly connected components using Kosaraju's algorithm. 2) Consider a strongly connected component. Consider an edge u. Now consider all edges from u to some vertice v. If v lies in some other SCC, eliminate the whole strongly conected component. Else include all the elements in the solution.
However, I am constantly getting WA. Please help.
Here is my code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <fstream>
#include <iterator>
#include <queue>
using namespace std;
int k = 0;
int V, E;
bool fix[5001];
bool fix2[5001];
int compNum[5001];
void dfs(int v, vector< vector<int> >&G, bool *fix, vector <int> &out) {
fix[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix[u]) {
fix[u] = true;
dfs(u, G, fix, out);
}
}
out.push_back(v);
}
void dfs2(int v, vector< vector<int> >&G, bool *fix2, vector < vector<int> > &components) {
fix2[v] = true;
for (int i = 0; i < G[v].size(); i++) {
int u = G[v][i];
if (!fix2[u]) {
fix2[u] = true;
dfs2(u, G, fix2, components);
}
}
components[k].push_back(v);
compNum[v] = k;
}
int main() {
int a, b;
while (true) {
cin >> V; if (V == 0) break; cin >> E;
vector< vector<int> >G(V + 1);
vector< vector<int> >G2(V + 1);
vector<int>out;
vector < vector<int> >components(V + 1);
for (int i = 0; i < E; i++) {
cin >> a >> b;
G[a].push_back(b);
G2[b].push_back(a);
}
for (int i = 1; i <= V; i++) {
if (!fix[i])
dfs(i, G, fix, out);
}
reverse(out.begin(), out.end());
for (int i = 0; i < out.size(); i++){
if (!fix2[out[i]]) {
dfs2(out[i], G2, fix2, components);
k++;
}
}
vector<int>gamotana;
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
bool check = true;
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
check = false; goto next123;
}
}
if (check)
gamotana.push_back(components[i][j]);
}
next123:;
}
sort(gamotana.begin(), gamotana.end());
for (int i = 0; i < gamotana.size(); i++)
cout << gamotana[i] << " ";
for (int i = 0; i < 5001; i++) {
fix[i] = false;
fix2[i] = false;
compNum[i] = -1;
}
k = 0;
cout << endl;
}
return 0;
}
In your algorithm description you say you eliminate the entire connected component if some edge leads to a different component.
However, in your code you appear to add all vertices j in component i to your solution until you find an edge leading out. In other words, even if a component is not a sink you may still incorrectly report some of the vertices as being sinks.
I imagine you should do something more like this:
for (int i = 0; i < components.size(); i++) {
for (int j = 0; j < components[i].size(); j++) {
for (int z = 0; z < G[components[i][j]].size(); z++)
{
if (compNum[G[components[i][j]][z]] != i)
{
goto next123;
}
}
}
for (int j = 0; j < components[i].size(); j++)
gamotana.push_back(components[i][j]);
next123:;
}
Of course, there may be more issues. I would recommend you try constructing and testing some small examples first, and perhaps testing against a brute force solver to identify failing cases.
#include<bits/stdc++.h>
using namespace std;
void dfs(vector<int>* edges, stack<int>& finishedVertices, bool* visited, int n, int start){
visited[start] = true;
for(int i = 0 ; i < edges[start].size() ; i++){
int node = edges[start][i];
if(!visited[node]){
dfs(edges, finishedVertices, visited, n, node);
}
}
finishedVertices.push(start);
}
void dfs_reverse(vector<int>* edgesT, bool* visited, unordered_map<int,vector<int>>& SCC, int node, int k){
SCC[k].push_back(node);
visited[node] = true;
for(int i = 0 ; i < edgesT[node].size() ; i++){
int new_node = edgesT[node][i];
if(!visited[new_node]){
dfs_reverse(edgesT, visited, SCC, new_node, k);
}
}
}
void getSCC(vector<int>* edges, vector<int>* edgesT, int n){
bool* visited = new bool[n];
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
stack<int> finishedVertices;
for(int i = 0 ; i < n ; i++){
if(!visited[i]){
dfs(edges, finishedVertices, visited, n, i);
}
}
unordered_map<int,vector<int>> SCC;
int k = 0;
for(int i = 0 ; i < n ; i++){
visited[i] = false;
}
while(!finishedVertices.empty()){
int node = finishedVertices.top();
finishedVertices.pop();
if(!visited[node]){
dfs_reverse(edgesT, visited, SCC, node, k);
k++;
}
}
int flag = 1;
vector<int> ans;
vector<int> bottom;
for(int i = 0 ; i < k ; i++){
for(int j = 0 ; j < SCC[i].size(); j++){
ans.push_back(SCC[i][j]);
}
for(int m = 0 ; m < ans.size() ; m++){
int node = ans[m];
for(int j = 0 ; j < edges[node].size() ; j++){
int new_node = edges[node][j];
vector<int> :: iterator it;
it = find(ans.begin(), ans.end(), new_node);
if(it == ans.end()){
flag = 0;
break;
}
}
if(flag == 0)
break;
}
if(flag == 1){
for(int j = 0 ; j < ans.size() ; j++)
bottom.push_back(ans[j]);
}
flag = 1;
ans.clear();
}
sort(bottom.begin(), bottom.end());
for(int i = 0 ; i < bottom.size() ; i++)
cout << bottom[i] + 1 << " ";
cout << endl;
}
int main(){
while(true){
int n;
cin >> n;
if(n == 0)
break;
vector<int>* edges = new vector<int>[n];
vector<int>* edgesT = new vector<int>[n];
int e;
cin >> e;
for(int i = 0 ; i < e ; i++){
int x, y;
cin >> x >> y;
edges[x-1].push_back(y-1);
edgesT[y-1].push_back(x-1);
}
getSCC(edges, edgesT, n);
delete [] edges;
delete [] edgesT;
}
return 0;
}