I'm trying to solve the problem of the magic square in C ++ using Backtracking and recursion in C ++. Specifically for a 4x4 array.
An example of 4x4 magic square solution is as follows, in which each row, column and diagonal add 34:
The change that I have is this: The user enters some values that will start the algorithm.
My algorithm is this:
here you can appreciate better the image.
I have a notion of how the algorithm should work to solve the problem of the magic square with backtracking and recursion, but I've had problems.
One of them is:
Achievement not make my algorithm "ignore" the values that the user already entered.
My code in C++ is in this link in Github. And here is the code :
#include <iostream>
using namespace std;
int sudoku[4][4];
int row = 0;
int column = 0;
bool isFull(int s[4][4]){
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
if(s[4][4] == 0){
return false;
}
}
}
return true;
}
void printMatrix(int s[4][4]){
for(int i = 0; i < 4; i++){
for(int j = 0; j < 4; j++){
cout << sudoku[i][j] << " ";
}
cout << endl;
}
}
bool isAssigned(int row, int column){
if(row == 1 && column == 0 ||
row == 0 && column == 2 ||
row == 1 && column == 2){
return true;
} else return false;
}
bool verify(int s[4][4], int row, int column){
bool flag = false;
int sumrow = 0, sumcolumn = 0, sumDiagonal = 0, sumDiagonal2 = 0;
int value = 3;
for(int i = 0; i < 4; i++){
sumrow = sumrow + s[row][i];
sumcolumn = sumcolumn + s[i][column];
sumDiagonal = sumDiagonal + s[i][i];
sumDiagonal2 = sumDiagonal2 + s[i][value];
value--;
}
if(sumrow <= 34 && sumcolumn <= 34 && sumDiagonal2 <= 34 && sumDiagonal2 <= 34){
return true;
} else return false;
}
bool backtracking(int s[4][4], int row, int column){
if(isFull(s) == true){ //verify if there are no zeros in the matrix
printMatrix(sudoku);
cout<<"Solution find ";
}
else {
if(isAssigned(row, column) == false){ // verify if the cell is already assigned
for(int i = 1; i <= 16; i++){
s[row][column] = i; // assigned value
if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34
if(column == 4) {
row++;
column=0;
}
backtracking(s, row, column + 1); // recursion
printMatrix(s); // Print the matrix to see progress
cout<<endl;
} else { // the sum value exceeds 34
s[row][column] = 0;
return false;
}
}
}
}
}
int main(){
sudoku[1][0] = 5;
sudoku[0][2] = 15;
sudoku[1][2] = 10;
backtracking(sudoku, row, column);
return 0;
}
My algorithm is mainly the following:
Obviously some features in this case, but if you see my code you will realize what I try to do.
Perhaps my solution method does not work or is not good.
The reason for this publication is, I need help to improve or Need help to solve the code did. Here is my main function and output I get to run:
bool backtracking(int s[4][4], int row, int column){
if(isFull(s) == true){ //verify if there are no zeros in the matrix
printMatrix(sudoku);
cout<<"Solution find ";
}
else {
if(isAssigned(row, column) == false){ // verify if the cell is already assigned
for(int i = 1; i <= 16; i++){
s[row][column] = i; // assigned value
if(verify(s, row, column) == true){ // verify that the sum of the column, row and diagonal not greater 34
if(column == 4) {
row++;
column=0;
}
backtracking(s, row, column + 1); // recursion
printMatrix(s); // Print the matrix to see progress
cout<<endl;
} else { // the sum value exceeds 34
s[row][column] = 0;
return false;
}
}
}
}
}
output:
3 16 15 0
5 0 10 0
0 0 0 0
0 0 0 0
as I said before, I have problems when I find a value that the user was already assigned.
It is the first time working with backtracking, that is why I find it a bit difficult. Thanks for all.
Well, yes,
Had to do something similar lately, some places to get this "fixed"
Start with a bitmap (1-16) for the numbers already assigned in the grid. ie. those the user entered are already marked as being "used".
Only assign numbers to the grid that haven't been marked in that bitmap. If you use non-recursive methods, need to use a stack to know which have been tested to "unset" when backtracking. If using recursive methods (only 16 deep recursion ;) ) pass the bitmap and the already placed square as copies, not references ;)
As stated above, I am trying to get the elements of a 2D matrix using only C++
The matrix has MxN dimensions, and it may be so that N!=M, N >= M or M < N (basically the dimensions can be anything and are determined in execution time)
I have tried to go about it using 2 nested for loops but so far the code just keeps getting more & more complex & does not produce consistent results.
Visual aid:
I am trying to get the 2nd for loop to iterate through the colored cells of the matrix starting from top left - i.e. in every loop the amount/position of the cells that the 2nd loop iterates through keeps changing & I am starting to wonder whether this can be done at all given that N & M are not known on compile time.
Thanks for your time in advance.
~EDIT1:
Here is what the iteration of the elements would look like for a non square matrix (same thing applies if the rows where more than the columns)
~EDIT2:
Here is the code so far: (testable!)
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
void func(void);
// use these variables to specify the dimensions arbitrarily
// keep in mind I need this to work with relatively big matrices
int row = 5, col = 5;
string arr[][10]= {{"0", "0", "0", "0", "0", "0", "0", "0", "0", "0" },
{"0", "1,1", "1,2", "1,3", "1,4", "1,5", "1,6", "1,7", "1,8", "1,9" },
{"0", "2,1", "2,2", "2,3", "2,4", "2,5", "2,6", "2,7", "2,8", "2,9" },
{"0", "3,1", "3,2", "3,3", "3,4", "3,5", "3,6", "3,7", "3,8", "3,9" },
{"0", "4,1", "4,2", "4,3", "4,4", "4,5", "4,6", "4,7", "4,8", "4,9" },
{"0", "5,1", "5,2", "5,3", "5,4", "5,5", "5,6", "5,7", "5,8", "5,9" },
{"0", "6,1", "6,2", "6,3", "6,4", "6,5", "6,6", "6,7", "6,8", "6,9" },
{"0", "7,1", "7,2", "7,3", "7,4", "7,5", "7,6", "7,7", "7,8", "7,9" },
{"0", "8,1", "8,2", "8,3", "8,4", "8,5", "8,6", "8,7", "8,8", "8,9" },
{"0", "9,1", "9,2", "9,3", "9,4", "9,5", "9,6", "9,7", "9,8", "9,9" } };
bool f = false, f2 = false;
int main (void)
{
func();
return 0;
}
void func(void)
{
if(row < col)
{
//remember that row > col
f = true;
}
unsigned short m_i; //mask for the counter of the outer for loop (i) - counts how many times the
unsigned short j_end = 1; //stores the max number of iterations the inner loop should do - increments accordingly
unsigned short k = 1; //stores the starting index of the inner loop - starts incrementing once (j_end == col)
cout << "row = " << row << ", col = " << col << endl;
cout << "total \"i\" loops " << (row + col -1) << endl << endl;
for (unsigned short i=1; i<=row + col -1; i++) // row + col -1 is the total number of diagonals in any matrix
{ // and also the total number of iterations we need
if( i > row) // here I implement the row > col scenario, the rest should be similar
{
m_i = row; // the mask should never go above the max row number
}else if(i == row)
{
m_i = row;
if (f = true) f2 = true; // using f2 remember that we've reached the max number for rows
}else{
m_i = i; // (i < row) so just pass i
}
for(unsigned short j=k; j<=j_end; j++){
cout<< arr[m_i][j]<<" ";
if(m_i > 1){
m_i--;
}else{
m_i = 1;
}
}
cout<<endl<< "*************" << endl;
if(j_end == col )
{
k++; // increment starting index of inner loop
}else{
j_end++; // max number for inner loop not yet achieved so increment max number
}
if(m_i == row)
{
k++;
}
} // end outer loop
} // end func
You can use this code to test it for yourself the output should be something like this:
And you can change the row & col values to test for different dimensions.
So far I believe this code works for square matrices, but not so much when row != col
~EDIT3:
func() should take performance into consideration as I said before I expect the matrices to be quite large!
for( int manhattan_distance = 0; manhattan_distance < M + N - 1; ++manhattan_distance )
{
for( int i = 0; i <= manhattan_distance; ++i )
{
int j = manhattan_distance - i;
if( j < N && i < M )
{
...
}
}
}
Code:
#include <vector>
#include <utility>
#include <iostream>
int main() {
int n, m;
std::cin >> n >> m;
std::vector<std::pair<int, int> > result;
for (int k = 0; k < m; k++) {
int i = 0, j = k;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
for (int k = 1; k < n; k++) {
int i = k, j = m - 1;
while (i < n && j >= 0)
{
result.push_back({ i, j });
i++;
j--;
}
}
return 0;
}
Explanations:
If you look at the picture, you can see that diagonal is when you move i + 1 and j - 1. Until the first half, we start from the first row and try to go in direction specified. When we hit the end, we just go to the next column. Basically, every iteration we are just changing the starting point. The second part is a bit trickier, because we already traversed some of the lines, so we start from 1 (because we already traversed first row. Then applying the same direction as in the first half, we traverse the rest of the matrix.
You can do it like this:
void foo(int rows,int cols){
// first go vertically down
for (int start_row = 0;start_row<rows;start_row++){
int col = 0;
int row = start_row;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
// now horizantally
for (int start_col = 0;start_col<cols;start_col++){
int col = start_col;
int row = rows-1;
while (col < cols && row >= 0){
std::cout << row << "," << col << " ";
row--;
col++;
}
std::cout << std::endl;
}
}
It might be possible to write it more compact, but it works.
OK I got an answer for this, all thought its not refined.
It is working properly but it is not optimized.
EDIT: c#... did not see it was for c++, but the idea is the same
using System;
Random r = new Random();
int rows = r.Next(10,13); // or any range of rows
int cols = r.Next(10,20); // same applies
int[,] matrix = new int[rows,cols];
// mark upper diagonal
for(var i=0; i<= cols; i++)
markByCol(i,0,cols-i);
// mark lower diagonal
for(var i=1; i<= rows; i++)
markByCol(cols+1+i,i,cols-1);
// stringify matrix to view it properly
string line = string.Empty;
for(int i=0; i< rows; i++)
{
line = string.Empty;
for(int j=0; j< cols; j++)
{
line+= matrix[i,j]+" | ";
}
Console.WriteLine(line);
}
// the actual function
int markByCol(int marker,int row,int col){
if((row > -1 && row < rows) && (col > -1 && col < cols))
{
matrix[row,col] = marker;
return markByCol(marker,row+1,col-1);
}
else
return 0;
}
Here is a jsFiddle. just hit play. This implementation marks each diagonal with a specific integer so you can scan and categorize each cell by its value, in terms of which diagonal crosses it.
https://dotnetfiddle.net/Qy8J1O
I'm trying to solve Sudoku by recursive. The program working great. The problem is that the stack is only keep-able of 4-6K recursive. That's mean that if I'm leaving the soduku with more than 6-7 empty cells, the combination needed to solve it is:
4^7 = 16384 > 4-5K...
How can I improve my program to work with less calls? The program is working good out of this problem. The function:
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N])
is all the business.
I give you here all the numbers you need for correct soduku to not wast your time. You can some of them out and see how it's work:
0 0 1
0 1 2
0 2 3
0 3 4
1 0 4
1 1 3
1 2 2
1 3 1
2 0 3
2 1 1
2 2 4
2 3 2
3 0 2
3 1 4
3 2 1
3 3 3
-1
and the code:
#include <iostream>
using namespace std;
const int N = 2;
void zero_soduku(int soduku[][N*N]);
void zero_arr(int temp_arr[], int size);
void get_input(int soduku[][N*N], bool fixed_values[][N*N]);
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]);
bool check_soduku(const int soduku[][N*N]);
bool check_rows(const int soduku[][N*N]);
bool check_cols(const int soduku[][N*N]);
bool check_sub_interval(const int soduku[][N*N]);
void print_soduku(const int soduku[][N*N]);
int main() {
int soduku[N*N][N*N] = { 0 }, row = 0, col = 0;
bool fixed_values[N*N][N*N] = { false };
get_input(soduku, fixed_values);
solve_soduku(soduku, row, col, fixed_values);
cout << endl;
print_soduku(soduku);
system("pause");
return EXIT_SUCCESS;
}
bool check_soduku(const int soduku[][N*N]) {
if (check_rows(soduku) && check_cols(soduku) && check_sub_interval(soduku))
return true;
return false;
}
bool check_rows(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[i][j] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_cols(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto i = 0; i < N*N; i++) {
zero_arr(temp_arr, N*N);
for (auto j = 0; j < N*N; j++)
temp_arr[soduku[j][i] - 1]++;
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
}
return true;
}
bool check_sub_interval(const int soduku[][N*N]) {
int temp_arr[N*N] = { 0 };
for (auto rows_intervals = 0; rows_intervals < N; rows_intervals++)
for (auto cols_intervals = 0; cols_intervals < N; cols_intervals++)
for (auto i = rows_intervals*N; i < rows_intervals*N + N; i++)
for (auto j = cols_intervals*N; j < cols_intervals*N + N; j++) {
temp_arr[soduku[i][j] - 1]++;
//end of interval, check if !good interval
if (i == rows_intervals*N + N - 1 && j == cols_intervals*N + N - 1) {
for (auto k = 0; k < N*N; k++)
if (temp_arr[k]>1)
return false;
zero_arr(temp_arr, N*N);
}
}
return true;
}
void solve_soduku(int soduku[][N*N], int &row, int &col, const bool fix_v[][N*N]) {
static int counter = 0;
counter++;
cout << endl << counter << endl;
//Not empty cell
if (soduku[row][col] != 0)
//Not end of line
if (col < N*N - 1) {
col++;
solve_soduku(soduku, row, col, fix_v);
}
else
//Not end of rows
if (row < N*N - 1) {
row++;
col = 0;
solve_soduku(soduku, row, col, fix_v);
}
else
//end of soduku
if (check_soduku(soduku)) {
print_soduku(soduku);
return;
}
/////// Finishd soduku but answaer not good //////////////////
else
//Last cell not max
if (soduku[row][col] < N*N - 1) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
//Last cell max, going back...
else {
while (soduku[row][col] == N*N || fix_v[row][col]) {
if (!fix_v[row][col]) {
soduku[row][col] = 1;
print_soduku(soduku);
cout << endl;
}
if (col > 0) {
col--;
continue;
}
if (col == 0 && row > 0) {
col = N*N - 1;
row--;
}
}
if (!fix_v[row][col]) {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
}
solve_soduku(soduku, row, col, fix_v);
}
//////////////////////////////////////////////////////////////////////////
//Empty cell
else {
soduku[row][col]++;
print_soduku(soduku);
cout << endl;
solve_soduku(soduku, row, col, fix_v);
}
}
void zero_arr(int temp_arr[], int size) {
for (auto i = 0; i < size; i++)
temp_arr[i] = 0;
}
void zero_soduku(int soduku[][N*N]) {
for (int i = 0; i < N*N; i++)
for (int j = 0; j < N*N; j++)
soduku[i][j] = 0;
}
void get_input(int soduku[][N*N], bool fixed_values[][N*N]) {
cout << endl << "Please enter locatin and nums into soduku: ";
int row = 0, col, value;
while (row != -1) {
cin >> row;
if (row == -1)
return;
cin >> col >> value;
soduku[row][col] = value;
fixed_values[row][col] = true;
}
}
void print_soduku(const int soduku[][N*N]) {
for (auto i = 0; i < N*N; i++)
for (auto j = 0; j < N*N; j++) {
cout << soduku[i][j] << " ";
if (j == N*N - 1)
cout << endl;
}
//system("pause");
}`enter code here`
Your algorithm appears to be, roughly:
1) Try each move in turn
2) Check the entire board to see if it's valid
3) Repeat until the entire board is filled
This is obviously very inefficient. The code will be making many moves which are illegal, then only realizing this belatedly, after fact.
I would suggest that you completely get rid of this, and attempt to implement something a little bit more efficient. Try to think how carbon-based life forms solve sudoku puzzles, and implement the same algorithm. Do you also do the above approach, when you solve a sudoku puzzle? Of course not. You do something like this:
1) For each position on the board, instead of storing just the current number in that position, if any, also store additional information: namely, if there is no number in that position, also store all possible numbers which would legal moves for that position.
For a completely empty board, for example, each position on the sudoku board would contain all values 1-9. From this, we then make the next logical step:
2) When making a move and placing a value in some position, say 4, you will remove the value 4 from all other cells in its 3x3 square, and remove 4 from all other cells in the same row and column. Because that number will no longer be a valid move in those cells. Conversely, when undoing a move, and removing the 4 from the cell, this means that the value 4 is now legal in all cells in its 3x3 square, and its row and column, so you would put this value in all of those positions, as a number that's now a legal move in those positions.
3) When deciding which next move to make, scan the board first, looking for any cell that has only one possible legal number. This means, of course, that this is the only legal move for that cell, so you make it.
4) If you find any cell that has no legal values left, this means that you reached an unsolvable state, so you'll undo your last move, and then try the next valid move from that point on.
5) Otherwise, you should just pick one of the cells that has the fewest possible legal moves left, make the first move, then keep going, then if you reach an unsolvable state, and return to this move, you undo it, and try the next move.
This seems to me an approach that should be much more efficient, as it should end up making the least number of illegal moves.
It is also closely mimics how carbon-based lifeforms solve sudoku puzzles by themselves.
P.S. To initialize a new sudoku puzzle with prefilled numbers, just start with an empty sudoku board, with all cells allowing all numbers 1-9 as legal moves, then make each move, as described above, to fill in the initial numbers on the sudoku board.