I am a C++ noob and I have just started learning it, and one of my assignments is to print a solution to the N-Queens problem, where the board would be N*N depending on user input. My IDE keeps showing me errors I don't understand in my code, even though to me it looks good and fine.
#include <iostream>
#include <array>
#include <stdexcept>
using namespace std;
int N;
bool safe(char board[N][N], int row, int col)
{
//checks if it's safe to place a queen
//doesn't give me any errors
}
bool placeQueen(char board[N][N], int col)
{
for (int i = 0; i < N; i++)
{
if ( safe(board, i, col) )
// says there is no matching function to call safe
{
board[i][col] = 1;
if ( placeQueen(board, col + 1) ){
//says cannot initialize parameter of type char(*)[*]
//with an Ivalue of type char(*)[N]
return true;
}
board[i][col] = 0;
}
}
return false;
}
void printAnswer(char board[N][N]){
//prints the final answer
}
int main()
{
int i, j;
try{
cout << "Enter the number of queens: ";
cin >> N;
char board[N][N];
for (int i = 0; i < N; i++){
for (int j = 0; i < N; i++){
board[i][j] = '.';
}
}
if ( placeQueen(board, 0) == false )
//no matching function to call placeQueen
{
throw runtime_error("Solution does not exist.");
return 0;
}
printAnswer(board);
//no matching function to call printAnswer
}
catch (runtime_error& excpt){
cout << excpt.what();
}
return 0;
}
It's probably me just being stupid but help would be appreciated, thanks!
char board[N][N] is not C++ when N is not a compile time constant. It's an extension by gcc that really shouldn't be on by default.
You are not defining functions that take (C style) arrays of arrays of char, but instead they take something that isn't defined in standard C++, and behaves differently to how it would in C.
You should instead define some other type as your board, e.g. using Board = std::vector<std::vector<char>>;. Then you can pass (references to) this type around.
#include <iostream>
#include <vector>
using Board = std::vector<std::vector<char>>;
bool safe(const Board & board, int row, int col)
{
//checks if it's safe to place a queen
//doesn't give me any errors
}
bool placeQueen(Board & board, int col)
{
for (int i = 0; i < N; i++)
{
if (safe(board, i, col) )
{
board[i][col] = 1;
if ( placeQueen(board, col + 1) ){
return true;
}
board[i][col] = 0;
}
}
return false;
}
void printAnswer(const Board & board){
//prints the final answer
}
int main()
{
std::cout << "Enter the number of queens: ";
int N;
std::cin >> N;
Board board{N, {N, '.'}}; // Initialise N vectors of N '.'
if (!placeQueen(board, 0))
{
std::cout << "Solution does not exist.";
return 0;
}
printAnswer(board);
return 0;
}
For the life of me I can't get this code to sort correctly. This is a recursion practice, by sorting five numbers that the user inputs, then I display those five numbers from least to greatest. It does most of it correctly, but occasionally it will mess the first or last number up, and switch it with another number in the array. I know the problem is inside the function where is does the swapping, in that second 'if' statement, but I can't figure out how to fix it, I would really appreciate some direction as to how to proceed. Here is my code:
#include <iostream>
#include <array>
using namespace std;
void mySort(int nums[], int first, int size);
int main()
{
int fiveNumbers[5];
int firstNum = 0;
int size = 5;
cout << "Please enter five numbers, pressing enter after each.\n\n";
for (int i = 0; i < 5; i++)
{
cout << "Enter a number: ";
cin >> fiveNumbers[i];
cout << endl;
}
mySort(fiveNumbers, firstNum, size);
for (int i = 0; i < size; i++)
{
cout << fiveNumbers[i] << endl;
}
system("PAUSE");
return 0;
}
void mySort(int nums[], int first, int size)
{
if (size == 0)
{
return;
}
for (int i = 0; i < 5; i++)
{
if (first < nums[i])
{
swap(nums[first], nums[i]);
}
}
first++;
size--;
return mySort(nums, first, size);
}
Changed my function to reflect the value of the array AT point 'first', instead of the variable 'first' itself. So far it has worked every time!
void mySort(int nums[], int first, int size)
{
if (size == 0)
{
return;
}
for (int i = 0; i < 5; i++)
{
if (nums[first] < nums[i])
{
swap(nums[first], nums[i]);
}
}
first++;
size--;
return mySort(nums, first, size);
}
EDIT: Got your code working but forgot the most important part, namely:
You're comparing the index to the array value, use:
if (nums[first] < nums[i])
Instead of:
if (first < nums[i])
Also, you always start swapping from the beginning when you should be starting one past first.
Instead of:
for (int i = 0; i < 5; i++)
You want:
for (int i = first + 1; i < 5; i++)
I have a class called magicSquare with a constructor and a display function called display. The constructor creates the magic square, and the display function displays the results. In my main function, I created an instance of magicSquare called ms and gave it a value 7. To display it, shouldn't it work if I just did ms.display()?
class magicSquare
{
private:
int size, square;
vector<vector <int> > finalvec;
public:
magicSquare(int a):finalvec(a, std::vector<int>(a))
{
int i = 0;
int j = a/2;
size = a;
square = a * a;
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
for (int k=0; k < square; ++k)
{
finalvec[i][j] = k;
i--;
j++;
if (k%a == 0)
{
i = i+ 2;
--j;
}
else
{
if (j==a)
j = j- a;
else if (i<0)
i = i+ a;
}
}
}
void display()
{
for (int i = 0; i < size; i++)
{
for (int j = 0; j< size; j++)
cout << finalvec[i][j];
cout << endl;
}
}
};
int main()
{
magicSquare ms(3);
ms.display();
return 0;
}
Your Error
As pointed by #Retired Ninja, the vector > finalvec(a,vec); hide your member variable finalvec, as you redefine it as a new vector...
What can correct it
You could construct your vector inside a Member initializer list like this
magicSquare(int a) : finalvec(a, std::vector<int>(a, 0)) {
/* your constructor */
}
And delete the two line:
vector<int>vec(a);
vector<vector<int> > finalvec(a,vec);
In your code
How to not make this error
Seeing which value are a class member, method parameter or even context variable can be sometime difficult:
What i can recommend you is to do the following:
class member -> m_NAME_OF_YOUR_CLASS_MEMBER
method parameter -> t_NAME_OF_YOUR_METHODE_PARAMETER
context variable -> c_NAME_OF_YOUR_CONTEXT_VARIABLE
by doing this error like you've done is a bit harder to do!
EDIT: After testing your code
I see there's error in it, effectively, the first time you go in that line:
finalvec[i][j] = k;
i > size, so you access further that your vector allow it, which result in a segfault! please repair your code!
hope that can help
I've been trying to solve the N queen problem using backtracking. Most of the approaches that I found online, involved vectors, making it difficult for me to visualize the solutions as some applets on the Internet do.
The solution I came up with, is giving me many problems(which i have a feeling are related to indexing of the dynamic 2D array used) and I'm not able to figure it out using Dev-C++ debugger.Any help and/or constructive criticism is highly appreciated. Many thanks in advance.
Here is the solution that i came up with:
#include<iostream>
#include<string.h>
#include<conio.h>
using namespace std;
void display(char** b, int len);
void initialize(char** &b, int k);
void consider1strow(char ** b, int len);
void markunsafe(char** board, int rowno, int colno);
void marksafe(char** board, int rowno, int colno);
void considerrow(char** board, int rowno);
void backtrack(char** board, int rowno);
bool checksafety(char** board, int rowno, int colno);
void place(char** board, int rowno, int colno);
void solve(char** board, int len);
int state[20] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
int len;
void display(char** board, int len)
{
int i, j;
cout << endl << "The current state of the board:" << endl;
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
cout << board[i][j];
}
cout << endl;
}
}
void initialize(char** &b, int k)
{
int i, j;
//create dynamic board
b = new char*[k];
for (i = 0; i < k; i++)
{
b[i] = new char[k];
}
//initialize array
for (i = 0; i < k; i++)
{
for (j = 0; j < k; j++)
{
b[i][j] = '-';
}
}
}
void consider1strow(char ** board, int len)
{
int col;
cout << "Enter the column to try for the first row!";
cin >> col;
board[0][col - 1] = 'Q';
state[0] = col - 1;
markunsafe(board, 0, col - 1);
display(board, len);
}
void markunsafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as unsafe
for (i = 0; i < len; i++)
{
board[rowno][i] = 'x';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = 'x';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = 'x'; //check if index gives a problem of +/- 1
}
}
}
board[rowno][colno] = 'Q';
}
void marksafe(char** board, int rowno, int colno)
{
int i, j;
//mark row as safe
for (i = 0; i < len; i++)
{
board[rowno][i] = '-';
}
//mark column as unsafe
for (i = 0; i < len; i++)
{
board[i][colno] = '-';
}
//mark unsafe diagonals
for (i = 0; i < len; i++)
{
for (j = 0; j < len; j++)
{
if ((rowno + colno) == (i + j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
if ((rowno - colno) == (i - j))
{
board[i][j] = '-'; //check if index gives a problem of +/- 1
}
}
}
}
void considerrow(char** board, int rowno)
{
bool safe = 0;
int i;
for (i = 0; i < len; i++)
{
safe = checksafety(board, rowno, i);
if (safe && (i >= state[rowno]))
{
break;
}
}
if (safe && (i >= state[rowno]))
{
place(board, rowno, i);
}
else if (!safe)
{
backtrack(board, rowno);
}
}
void backtrack(char** board, int rowno)
{
marksafe(board, rowno - 2, state[rowno - 2]);
considerrow(board, rowno);
}
bool checksafety(char** board, int rowno, int colno)
{
if (rowno == 0)
{
return 1;
}
else if (board[rowno][colno] == 'x')
{
return 0;
}
else if (board[rowno][colno] == '-')
{
return 1;
}
}
void place(char** board, int rowno, int colno)
{
board[rowno][colno] = 'Q';
state[rowno] = colno;
markunsafe(board, rowno, colno);
}
void solve(char** board, int len)
{
int i = 0;
if (i == len)
{
display(board, len);
}
else
{
consider1strow(board, len);
for (i = 1; i < len; i++)
{
considerrow(board, i);
}
}
}
int main()
{
char** board;
cout << "Enter the size of the board!";
cin >> len;
initialize(board, len);
solve(board, len);
getch();
}
It is running after the initial configuration, but you're not printing it. Change this (inside solve):
for(i=1;i<len;i++)
{considerrow(board,i);}
for this:
for(i=1; i<len; i++) {
considerrow(board,i);
display(board,len);
}
Besides that, there is a problem with the way you are doing backtracking. If no options are available, you are removing the queen from the previous row (that's ok) and then you are marking every cell it was attacking as safe (not ok). The problem is that some of these cells may be under attack by a different queen, so you cannot mark them as safe. Furthermore, you do not place a different queen on that row. I propose some solutions:
First, make it recursive: considerrow would call itself with the following row, and return true (1) if it succeeds or false (0) if it fails. If it fails with the next row, you can use the next queen in the current row and call considerrow again, until you succeed or run out of columns, in which case you return false.
To consider a different queen on a certain row, you can do two things: create a copy of the board which you would pass to considerrow for the next row (and thus keeping a 'before' copy to try a different queen), or mark every cell as safe, and then check all the existing queens to mark cells unsafe.
Edit:
To make it recursive, we are going to make considerrow call itself with the next value.
bool considerrow(char** board,int rowno) {
//Print the board
display(board,len);
bool safe=0;
int i;
for(i=0; i<len; i++) {
safe=checksafety(board,rowno,i);
if(safe) {
place(board,rowno,i);
//Is this the last row? If so, we suceeded
if (rowno==len-1) return 1;
//Call itself with next row, check if suceeded
if (considerrow(board,rowno+1))
return 1;
else //Failed, try a different row
backtrack(board,rowno);
}
}
return 0; //If we got here, then we ran out of colums. Return failure
}
The backtrack function can be modified to revert the current row like this:
void backtrack(char** board, int rowno) {
//Clear the current row
marksafe(board,rowno,state[rowno]);
//Check that every cell attacked by another queen is marked unsafe
for(int i=0; i<rowno; i++) markunsafe(board,i,state[i]);
}
Doing that, solve will only need to call the first row:
void solve(char** board,int len) {
considerrow(board,0);
display(board,len);
}
I wanted to make a pyramid like this:-
____*
___*_*
__*___*
_*_____*
*********
for n=5.
the lines are not underscores but spaces.
My try:-
#include <iostream.h>
void main()
{ int i,k,l,n;
cin>>n;
for(i=1; i<=n-1; i++)
{
for(k=1; k<=i; k++)
{if((k==n+i-1)||(k==n-i+1))
cout<<"*";
else
cout<<" ";
}
cout<<"\n";
}
for(l=1; l<=2*n-1; l++)
cout<<"*";
}
But the output comes as:-
__ *
_*
Note: This is a turbo c++ program.
UPDATE:
With some optimization and by taking n as row count instead of base width, we have something very simple:
void drawPyramid(const int &n) {
int b=2*n-1;
for (int i=b/2; i>=0; i--) {
for (int j=0;j<b-i; j++) {
if (i==0 || j==i || j==b-i-1) {
std::cout<<"*";
} else {
std::cout<<" ";
}
}
std::cout<<std::endl;
}
}
Old:
It was quite funny to do, but it works as well. My approach is to start a counter from the maximum width that the pyramid may have at the end, then divide the problem into two distinct steps:
Go to the first edge
Go to the second edge
It sure can be optimized but it will give you the idea:
int drawPyramid(const int &baseWidth, const char &edgeChar, const char &outsideChar, const char &insideChar) {
// test if base width allows to have a single char at the top of it
if (baseWidth%2==0) {
std::cout<<"Error in 'drawPyramid(const int &baseWidth)': Pyramid base width must be an odd number for the top to match"<<std::endl;
return 0;
}
for (int i=baseWidth; i>=0; i-=2) { // the first edge is initially far, then gets closer
int j=0;
// Go to first edge
while (j<i/2) {
std::cout<<outsideChar;
j++;
}
std::cout<<edgeChar;
if (i==1) { // at the bottom of the pyramid
for (int k=0; k<baseWidth-1; k++) {
std::cout<<edgeChar;
}
} else if (i<baseWidth) { // test if there is a second edge to reach
// Go to second edge
while (j<baseWidth-i/2-2) {
std::cout<<insideChar;
j++;
}
std::cout<<edgeChar;
}
// Done with the current line
std::cout<<std::endl;
}
return 1;
}
Hope this helps :)
modify your loop to this and it works
for(i=1; i<=n-1; i++)
{
for(k=1; k<i + n; k++) // greater range than previously to include whole triangle
{if((k==n+i-1)||(k==n-i+1)) // == instead of --
cout<<"*";
else
cout<<" ";
}
cout<<"\n";
}
for(l=1; l<=2*n-1; l++)