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 ;)
Related
I want to compare two arrays. One of them is a subset of the other one. I want my function to return the minimum and equal gap between the numbers of the first subset array in the other array.
For example if I have
arr1 = 2,1,4,2,8,3
sub= 1,2,3
I want my function to return 1 because the mimimum gap between all this numbers are 1.
arr1 = 2,1,5,2,1,2,3
sub= 1,2,3
I want my function to return 0 because the mimimum gap between 1,2,3 in arr1 is 0
Here is the code I am trying to do: My code always return 0 can you help me understand why, and how can I solve this.
int gap(int* arr, int* sub, int sizeArr, int sizeSub)
{
int index = 0; int gap = 0; bool flag = true;
int i = -1;
for (int jump = 1; jump < sizeArr / sizeSub; jump++)
{
index = 0;
for (i = i +1; i < sizeArr; i++)
{
if (sub[index] == arr[i])
{
for (int j = i + jump, index = 1; j < sizeArr; j = j + jump, index++)
{
if (arr[j] != sub[index]) { flag = false; break; }
else if (arr[j] == sub[index] && index == sizeSub) { flag = true; break; }
}
}
if (!flag) { break; }
else { gap = jump; break; }
}
}
return gap;
}
You initially took gap equally 0 but i think more suit to not store gap
and start iterate jump from 0. And return jump immediately after you found that it is suit.
Also i think that store index in such manner as you it is bad idea, because you code return wrong answer on
int a[] = { 2,1,4,4,2,8,5,3 };
int s[] = { 1,2,3 };
I think you should declare variable as soon as possible, otherwise there will be undesirable side effects.
So you code can be rewritten as
int gap(int *arr, int *sub, int sizeArr, int sizeSub)
{
for (int jump = 0; 1 + (jump + 1) * (sizeSub - 1) <= sizeArr; jump++) {
for (int start_index = 0; start_index + (jump + 1) * (sizeSub - 1) < sizeArr; start_index++) {
bool flag = true;
for (int index = 0; index < sizeSub; ++index) {
if (arr[start_index + index * (jump + 1)] != sub[index]) {
flag = false;
break;
}
}
if (flag) {
return jump;
}
}
}
return -1; //or some value that indicate that there is no answer
}
Homework: I'm just stumped as hell. I have algorithms set up, but I have no idea how to code this
Just to be clear you do not need arrays or to pass variables by reference.
The purpose of the project is to take a problem apart and using Top-Down_Design or scratch pad method develop the algorithm.
Problem:
Examine the numbers from 2 to 10000. Output the number if it is a Dual_Prime.
I will call a DualPrime a number that is the product of two primes. Ad where the two primes are not equal . So 9 is not a dual prime. 15 is ( 3 * 5 ) .
The output has 10 numbers on each line.
My Algorithm set-up
Step 1: find prime numbers.:
bool Prime_Number(int number)
{
for (int i = 2; i <= sqrt(number); i++)
{
if (number % 1 == 0)
return false;
}
return true;
}
Step 2: store prime numbers in a array
Step 3: Multiply each array to each other
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int j = 0; j < Size- 1; j++)
{
Dual_Prime[] = Arr[j] * Arr[j + 1]
}
}
Step 4: Bubble sort
void Bubble_Sort(int Array[], int Size) // Sends largest number to the right
{
for (int i = Size - 1; i > 0; i--)
for (int j = 0; j < i; j++)
if (Array[j] > Array[j + 1])
{
int Temp = Array[j + 1];
Array[j + 1] = Array[j];
Array[j] = Temp;
}
}
Step 5: Display New Array by rows of 10
void Print_Array(int Array[], int Size)
{
for (int i = 0; i < Size; i++)
{
cout << Dual_Prime[i] << (((j % 10) == 9) ? '\n' : '\t');
}
cout << endl;
}
I haven't learned dynamic arrays yet,
Although dynamic arrays and the sieve of Eratosthenes are more preferable, I tried to write minimally fixed version of your code.
First, we define following global variables which are used in your original implementation of Multiply_Prime_Numbers.
(Please check this post.)
constexpr int DP_Size_Max = 10000;
int DP_Size = 0;
int Dual_Prime[DP_Size_Max];
Next we fix Prime_Number as follows.
The condition number%1==0 in the original code is not appropriate:
bool Prime_Number(int number)
{
if(number<=1){
return false;
}
for (int i = 2; i*i <= number; i++)
{
if (number % i == 0)
return false;
}
return true;
}
In addition, Multiply_Prime_Numbers should be implemented by double for-loops as follows:
void Multiply_Prime_Numbers(int Array[], int Size)
{
for (int i = 0; i < Size; ++i)
{
for (int j = i+1; j < Size; ++j)
{
Dual_Prime[DP_Size] = Array[i]*Array[j];
if(Dual_Prime[DP_Size] >= DP_Size_Max){
return;
}
++DP_Size;
}
}
}
Then these functions work as follows.
Here's a DEMO of this minimally fixed version.
int main()
{
int prime_numbers[DP_Size_Max];
int size = 0;
for(int j=2; j<DP_Size_Max; ++j)
{
if(Prime_Number(j)){
prime_numbers[size]=j;
++size;
}
}
Multiply_Prime_Numbers(prime_numbers, size);
Bubble_Sort(Dual_Prime, DP_Size);
for(int i=0; i<DP_Size;++i){
std::cout << Dual_Prime[i] << (((i % 10) == 9) ? '\n' : '\t');;
}
std::cout << std::endl;
return 0;
}
The Sieve of Eratosthenes is a known algorithm which speeds up the search of all the primes up to a certain number.
The OP can use it to implement the first steps of their implementation, but they can also adapt it to avoid the sorting step.
Given the list of all primes (up to half the maximum number to examine):
Create an array of bool as big as the range of numbers to be examined.
Multiply each distinct couple of primes, using two nested loops.
If the product is less than 10000 (the maximum) set the corrisponding element of the array to true. Otherwise break out the inner loop.
Once finished, traverse the array and if the value is true, print the corresponding index.
Here there's a proof of concept (implemented without the OP's assignment restrictions).
// Ex10_TwoPrimes.cpp : This file contains the 'main' function. Program execution begins and ends there.
#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void Homework_Header(string Title);
void Do_Exercise();
void Sieve_Of_Eratosthenes(int n);
void Generate_Semi_Prime();
bool Semi_Prime(int candidate);
bool prime[5000 + 1];
int main()
{
Do_Exercise();
cin.get();
return 0;
}
void Do_Exercise()
{
int n = 5000;
Sieve_Of_Eratosthenes(n);
cout << endl;
Generate_Semi_Prime();
}
void Sieve_Of_Eratosthenes(int n)
{
// Create a boolean array "prime[0..n]" and initialize
// all entries it as true. A value in prime[i] will
// finally be false if i is Not a prime, else true.
memset(prime, true, sizeof(prime));
for (int p = 2; p*p <= n; p++)
{
// If prime[p] is not changed, then it is a prime
if (prime[p] == true)
{
// Update all multiples of p
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
}
bool Semi_Prime(int candidate)
{
for (int index = 2; index <= candidate / 2; index++)
{
if (prime[index])
{
if (candidate % index == 0)
{
int q = candidate / index;
if (prime[q] && q != index)
return true;
}
}
}
return false;
}
void Generate_Semi_Prime()
{
for (int i = 2; i <= 10000; i++)
if (Semi_Prime(i)) cout << i << "\t";
}
So i have this variable I would like to pass it as function to following code down which still not working yet but any idea about it?? I would also be pleased to know if we can add ctime to track the arrival of the user thanks for your help ..
bool spt_1 [15][12] = {0}
and this is the code which I want to pass it so I can call it later on somewhere in my code
int col = 1;
int row = 1;
for (col = 1 ; row < 16 ; row ++) {
if (spot_1 [col][row] == 0) {
cout<<"There is a place reserved for you in spot, the first column , row number "<<" "<<row<<"."<<endl;
string choice;
do {
cout<<"\nDo you want to take that spot? Y/N.\n"<<endl;
cin>>choice;
cout<<"\n"<<endl;
transform(choice.begin(), choice.end(), choice.begin(), toupper);
}while (choice != "Y" && choice !="YE" && choice != "YES" && cout<<"Wrong input!\n"<<endl);
cout<<"\nHave a nice day.\n"<<endl;
break;
if (choice == "YES") {
spot_1 [col][row] = 1; // should change that specific 0 to 1 ( which means occupied )
}
else {
//it should reject count ++;
}
if (spot_1 [col][row] != 0) { // When there is no more place it should cout this and go search in a new array and do same as first one
cout<<"Sorry ,There is no more place available , But you can go to :\n"<<endl;
}
}
}
}
thanks for your suggestions .
You should probably use a 2D vector instead of that array in the first place. But if you really need to do it with an array you could define a template function like this:
template <int Row, int Col>
void some_func(bool my_array[Row][Col])
{
//do your stuff
//here just printing the array and changing a value
for (int i = 0; i < Row; i++)
{
for (int j = 0; j < Col; j++)
std::cout << my_array[i][j];
std::cout << std::endl;
}
my_array[3][4] = false;
}
and call it in you program like this:
some_func<15,12>(spt_1);
EDIT after comment:
There is always a way, but it gets dirtier.
I would consider this more a C then a C++ question and I'm not a native C speaker.
I would maybe do it this way, but there are probably better ways:
void some_func(void* my_pointer, int row, int col)
{
bool* my_pointer_arr = static_cast<bool*>(my_pointer);
for (int i = 0; i < row * col; i += col)
{
for (int j = 0; j < col; j++)
std::cout << my_pointer_arr[i + j];
std::cout << std::endl;
}
my_pointer_arr[3 * col + 4] = false;
}
Maybe just search for "C style 2D array to function" and you will get a better answer.
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.
I'm trying to wiriting a sudoku generator algorithm, this is my c++ code:
void generateSudoku(num sudoku[][N])
{ int i,j,k;
int vett[N],n,old;
//clean the sudoku matrix filling it with -1
for(i=0;i<N;i++)
for(j=0;j<N;j++)
sudoku[i][j].val=-1;
//generate the sudoku
for(i=0;i<N;){
for(j=0;j<N;){
k=0;
clean(vett,N); //fills the vector with -1
old=sudoku[i][j].val; //saves the actual value
do{
if(k<9){
do{
n=rand()%9+1;
}while(find(vett,N,n)); //generate n while it already exists in vett
vett[k++]=n;
if((!(exists(sudoku,i,j,n))) && (n!=old)){ //if it not exists on row, column and sub-matrix and it's different between the old value, it's OK
sudoku[i][j++].val=n;
if(j==N) i++;
k=10;
}
}
else{
sudoku[i][j].val=-1;
if(j>0) j--;
else if(i>0){
j=N-1;
i--;
}
k=10;
}
}while(k<=9);
}
}
}
It goes in loop and I know the reason:
2 7 6 | 9 1 3 | 4 5 8
4 3 9 | 5 7 2 | * *
In this example it continues to generate 6-1 and then 1-6 where there are * and it never finishes. But even if I comprend why it loops, I don't know the best way to correct it. Can someone help me?
You have to backtrack further. There's no valid entry in the last cell of that second row. I'm not sure a greedy algorithm is going to work as sudoku generator. I'd try with a stack-tree based approach instead.
Following may help (untested) :
void restore(std::vector<int>& v) {
v.clear();
for (int i = 0; i != 9; ++i) {
v.push_back(1 + i);
}
}
void generate(int (&sudoku)[9][9])
{
std::vector<int> allowedSymbols[9][9];
bool succeed = true;
for(int i = 0, j = 0; i != 9; ) {
if (succeed) {
restore(allowedSymbols[i][j]);
succeed = false;
}
while (!allowedSymbols[i][j].empty()) {
int index = rand() % allowedSymbols[i][j].size();
if (!exists(sudoku, i, j, allowedSymbols[i][j][index])) { //if it not exists on row, column and sub-matrix, it is OK
succeed = true;
break;
}
allowedSymbols[i][j].erase(allowedSymbols[i][j].begin() + index);
}
if (succeed) {
++j;
if (j == 9) {
j = 0;
++i;
}
} else {
// backtrack.
--j;
if (j == -1) {
j = 8;
--i;
}
allowedSymbols[i][j].erase(std::find(allowedSymbols[i][j].begin(),
allowedSymbols[i][j].end(),
sudoku[i][j]));
}
}
}