Could anyone point the flaw in the code?
The idea that I used is backtracking with recurrence and I would like to stick to this way of sloving the given problem. When the variable moves is <= 60 couple of answers are printed instantly though the program is still running. If moves = 61,62 it takes couple of minutes to print some solutions and if moves = 63 no solution is printed within 15 mins in both cases the program is still running.
Here is the code:
//checking on which move was the square visited
int board[8][8] = {{1,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0},{0,0,0,0,0,0,0,0}};
int x = 0;//x and y coordinate of the knight's placement
int y = 0;
//move knight by
int move_to[8][8] = {{1,2},{-1,-2},{-1,2},{1,-2},{2,1},{-2,-1},{-2,1},{2,-1}};
//how many moves have been done
int moves = 0;
void solve()
{
//printing one solution
if(moves==63)
{
for(int k = 0; k < 8; k++)
{
for(int n = 0; n < 8; n++)
cout << setw(2) << board[k][n] << " ";
cout << "\n";
}
cout << "--------------------\n";
return;
}
else
{
for(int i = 0; i < 8; i++)
{
//checking if knight is not leaving the board
if(x+move_to[i][0]<0 || x+move_to[i][0]>7 || y+move_to[i][1]<0 ||
y+move_to[i][1]>7 || board[x+move_to[i][0]][y+move_to[i][1]]>0)
continue;
//moving theknight
x+=move_to[i][0];
y+=move_to[i][1];
//increasing the moves count
moves++;
//marking the square to be visited
board[x][y] = moves+1;
//backtracking
solve();
board[x][y] = 0;
x-=move_to[i][0];
y-=move_to[i][1];
moves--;
}
}
}
int main()
{
solve();
return 0;
}
I remember this problem from study. I do not fix them but I change initial position then the first path is found faster (that is how I passed this lab ;P). It is normal because
the number of path is too big.
But you can:
choose from move_to in random order
use multiple threads
Other hand you can read about "Constraint Programming"
Related
So I am currently working on a project to place N queens on an NxN board and prevent them from attacking each other. This project is for an intro level AI course. It has a few specific criteria to get full points which are, finding up to 3 solutions for any board size up to N = 100 in 5 seconds or less. I'm currently trying to make this a constraint satisfaction problem by choosing the most constrained row which if I understand it correctly will prevent rows that are closer to fully attacked from getting there.
Initially the user will input a column number and a queen will be placed in that column on the first row of the board. From there the attack board will be updated using that row column combination by increasing the value of all diagonals and the row and column a small example of the former and the latter below
void main()
{
int size, row, col;
row = 1;
cout << "Enter the board size: ";
cin >> size;
cout << "Enter column of first queen: ";
cin >> col;
cols[row] = col; // cols store the column value of each queen in that particular row.
updateAttack(row, col, +1, size);
findNextQueen(size);
// return here if we found all the solution
//cout << solutionCount << " solutions found. see NQueen.out.\n";
cout << solutionCount << " solutions found. see NQueen.out.\n";
fout.close();
system("pause");
}
void updateAttack(int r, int c, int change, int size) // Updates the attack board given the location a queen being placed
{
int r1, c1;
// update diagnals
for (r1 = r - 1, c1 = c - 1; r1 >= 1 && c1 >= 1; r1--, c1--)
attack[r1][c1] += change;
for (r1 = r + 1, c1 = c + 1; r1 <= size && c1 <= size; r1++, c1++)
attack[r1][c1] += change;
for (r1 = r - 1, c1 = c + 1; r1 >= 1 && c1 <= size; r1--, c1++)
attack[r1][c1] += change;
for (r1 = r + 1, c1 = c - 1; r1 <= size && c1 >= 1; r1++, c1--)
attack[r1][c1] += change;
// update columns
for (r1 = 1, c1 = c; r1 <= size; r1++) // k goes to each row
attack[r1][c1] += change;
}
The main issue with this program is choosing which row to place the queen in. In a simple backtracking method with recursive calls of the queen placing you increment down the rows and place the queen in the first space in that row that isn't currently under attack and then doing the same for the next row and the next queen until the queen cannot be placed, in which case you backtrack and attempt to fix the previous queen by moving it to the next spot. An example of this being done with backtracking and no CSP implemented below.
void findNextQueen(int r, int size)
{
for (int c=1;c<=size;c++)
{
if (attack[r][c]==0) // not under attack
{
cols[r]=c; // assign another queen
if (r<size)
{
updateAttack(r,c,+1, size);
findNextQueen(r+1, size);
updateAttack(r,c, -1, size);
}
else
{
print1solution(size);
if (solutionCount >= 3)
{
cout << solutionCount << " solutions found. see NQueen.out.\n";
system("pause");
exit(0);
}
}
}
}
return;
}
The constraint satisfaction attempts to solve a problem caused during this backtracking where you might later on completely fill rows below with attack values which will cause alot of backtracking to be required increasing the time it takes by alot of time. It does this by attempting to choose rows that have more spaces being attacked first in order to prevent them from being lost and requiring the late backtracking. My example of this that is causing the issues, currently that it always seems to come to 0 solutions possible below.
void findNextQueen(int size)
{
int bestRowCount = 0;
int bestRow = 2;
for (int r = 2; r <= size; r++) // Meant to find the most constrained row and use that as my r value for attack array
{
int aRowCount = 0; // Count of attacks in current row
for (int c = 1; c <= size; c++)
{
if (attack[r][c] >= 1)
{
aRowCount++;
}
}
if ((aRowCount > bestRowCount) && (aRowCount != size))
{
bestRowCount = aRowCount;
bestRow = r;
}
}
for (int c = 1; c <= size; c++)
{
if (attack[bestRow][c] == 0) // not under attack
{
cols[bestRow] = c; // assign another queen
if (queensLeft(size) == 1) // returns true if there are rows that still lack a queen
{
updateAttack(bestRow, c, +1, size);
findNextQueen(size);
cols[bestRow] = 0;
updateAttack(bestRow, c, -1, size);
}
else
{
print1solution(size);
if (solutionCount >= 3)
{
cout << solutionCount << " solutions found. see NQueen.out.\n";
system("pause");
exit(0);
}
}
}
}
return;
}
The very similar problem was introduced in LeetCode:
https://leetcode.com/problems/n-queens-ii
You can go to discussions and find explanation with code solutions.
You will need to modify code to return possible results when you reach your limit.
EDIT: Posting everything, because it gets really weird.
using namespace std;
int main()
{
int doors = -1;
int jumper = 1;
bool isOpen[100];
string tf;
for(int i = 0 ; i < 100; i++){
isOpen[i] = false;
}
while(jumper < 100){
while(doors < 100){
if(isOpen[doors + jumper] == true){
isOpen[doors + jumper] = false;
}
else{
isOpen[doors + jumper] = true;
}
doors += jumper;
cout << doors << endl;
}
doors = -1;
jumper+=1;
}
for(int i = 0; i < 100; i++){
if(isOpen[i]){
tf = "open";
}
else{
tf = "closed.";
}
cout << "Door " << i << " is " << tf << endl;
}
return 0;
}
So I'm having a very odd problem with this piece of code.
It's supposed to go through an array of 100 items. 0 - 99 by ones then tows then threes, etc. However, after a = 10, it shoots up to 266.
Can anyone tell me why?
Edit:
This problem only happens when the for loop is commented out. When it is left in the code, it does the same thing, but it doesn't happen until 19.
If I comment out the "string tf;" as well, it continues to loop at 99.
This is all based on the doors count.
I'm unsure why either of these should be a factor to the loop that neither are connected to.
According to your description this is what you should do:
for(int adv = 1, i = 0; adv < 100;)
{
// i is array index (your b) -> use it somehow:
doSomething(arr[i]);
i += adv;
if(i >= 100)
{
i = 0;
adv++;
}
}
The (probable) reason you got weird behavior (including the 266 value) is that your code overruns the buffer. When b will be high enough (say 99), you'd write to isOpen[b + a] which will be 100 or higher (100 if a is 1, and that's just the first iteration, later iterations will go much further). If the compiler allocates isOpen before the ints you'll be overwriting them.
I'm trying to write a program for university. The goal of the program is to make a nurse schedule for a hospital. However, i'm really stuck for the moment. Below you can find one function of the program.
The input for the function is a roster which consists of the shift each nurse has to perform on each day. In this example, we have 32 rows (32 nurses) and 28 columns (representing 28 days). Each cell contains a number from 0 to 6, indicating a day off (0) or a certain shift (1 to 6).
The function should calculate for each day, how many nurses are scheduled for a certain shift. For example, on the first day, there are 8 nurses which perform shift 2, 6 shift 3 and so forth. The output of the function is a double vector.
I think the function is mostly correct but when I call it for different rosters the program always gives the first roster gave.
void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
for (int i = 0; i < get_nbr_days(); i++)
{
vector<int> nurses_per_shift;
int nbr_nurses_free = 0;
int nbr_nurses_shift1 = 0;
int nbr_nurses_shift2 = 0;
int nbr_nurses_shift3 = 0;
int nbr_nurses_shift4 = 0;
int nbr_nurses_shift5 = 0;
int nbr_nurses_shift6 = 0;
for (int j = 0; j < get_nbr_nurses(); j++)
{
if (roster1[j][i] == 0)
nbr_nurses_free += 1;
if (roster1[j][i] == 1)
nbr_nurses_shift1 += 1;
if (roster1[j][i] == 2)
nbr_nurses_shift2 += 1;
if (roster1[j][i] == 3)
nbr_nurses_shift3 += 1;
if (roster1[j][i] == 4)
nbr_nurses_shift4 += 1;
if (roster1[j][i] == 5)
nbr_nurses_shift5 += 1;
if (roster1[j][i] == 6)
nbr_nurses_shift6 += 1;
}
nurses_per_shift.push_back(nbr_nurses_shift1);
nurses_per_shift.push_back(nbr_nurses_shift2);
nurses_per_shift.push_back(nbr_nurses_shift3);
nurses_per_shift.push_back(nbr_nurses_shift4);
nurses_per_shift.push_back(nbr_nurses_shift5);
nurses_per_shift.push_back(nbr_nurses_shift6);
nurses_per_shift.push_back(nbr_nurses_free);
nbr_nurses_per_shift_per_day.push_back(nurses_per_shift);
}
}
Here you can see the program:
Get_shift_assignment() and schedule_LD are other rosters.
void test_schedule_function()
{
calculate_nbr_nurses_per_shift(schedule_LD);
calculate_nbr_nurses_per_shift(get_shift_assignment());
calculate_coverage_deficit();
}
One more function you need to fully understand the problem is this one:
void calculate_coverage_deficit()
{
int deficit = 0;
for (int i = 0; i < get_nbr_days(); i++)
{
vector<int> deficit_day;
for (int j = 0; j < get_nbr_shifts(); j++)
{
deficit = get_staffing_requirements()[j] - nbr_nurses_per_shift_per_day[i][j];
deficit_day.push_back(deficit);
}
nurses_deficit.push_back(deficit_day);
}
cout << "Day 1, shift 1: there is a deficit of " << nurses_deficit[0][0] << " nurses." << endl;
cout << "Day 1, shift 2: there is a deficit of " << nurses_deficit[0][1] << " nurses." << endl;
cout << "Day 1, shift 3: there is a deficit of " << nurses_deficit[0][2] << " nurses." << endl;
cout << "Day 1, shift 4: there is a deficit of " << nurses_deficit[0][3] << " nurses." << endl;
}
So the problem is that each time I run this program it always gives me the deficits of the first roster. In this case, this is Schedule_LD. When I first run the function with input roster get_shift_assignment() than he gives me the deficits for that roster.
Apparently the nbr_nurses_per_shift_per_day[][] vector is not overwritten the second time I run the function and I don't know how to fix this... Any help would be greatly appreciated.
Let me try to summarize the comments:
By using global variables to return values from your functions it is very likely, that you forgot to remove older results from one or more of your global variables before calling functions again.
To get around this, return your results from the function instead.
Ex:
vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
vector<int> nbr_nurses_per_shift_per_day; // Create the result vector
... // Do your calculations
return nbr_nurses_per_shift_per_day;
}
or if you do not want to return a vector:
void calculate_nbr_nurses_per_shift(vector<vector<int>> roster1, vector<vector<int>> nbr_nurses_per_shift_per_day)
{
... // Do your calculations
}
But clearly, the first variant is a lot less error-prone (in the second example you can forget to clear nbr_of_nurses again) and most compilers will optimize the return nbr_nurses_per_shift_per_day so the whole vector does not get copied.
The second possible issue is that ´get_nbr_days()´ might return numbers that are larger or smaller than the actual size of your vector. To work around this, use either the size() method of vector or use iterators instead.
Your first function would then look like this:
vector<vector<int>> calculate_nbr_nurses_per_shift(vector<vector<int>> roster1)
{
vector<vector<int>> nbr_nurses_per_shift_per_day;
for (vector<vector<int>>::iterator shiftsOnDay = roster1.begin(); shiftsOnDay != roster1.end(); ++shiftsOnDay)
{
vector<int> nurses_per_shift(6, 0); // Create vector with 6 elements initialized to 0
for (vector<int>::iterator shift = shiftsOnDay->begin(); shift != shiftsOnDay->end(); ++shift)
{
if (*shift == 0)
nurses_per_shift[5]++;
else
nurses_per_shift[*shift - 1]++; // This code relies on shift only containing meaningful values
}
nbr_nurses_per_shift_per_day.push_back(nurses_per_shift);
}
return nbr_nurses_per_shift_per_day;
}
I'm trying to write code for the Knight's Tour:
A knight's tour is a sequence of moves of a knight on a chessboard such that the knight visits every square exactly once.
I've been trying to alter someone else's code, but the backtracking seems to not work properly - it never finds the solution. It works perfectly fine when the knight starts at 0, 0 but if it starts at any other spot on the 2D grid, the program goes on forever.
Where is the bug in this code?
#include <iostream>
#include <ctime>
using namespace std;
const int N = 8;
int map[N][N];
/* A utility function to check if i,j are valid indexes for N*N chessboard */
bool isSafe(int x, int y) {
return x >= 0 && x < N && y >= 0 && y < N && map[x][y] == -1;
}
/* A utility function to print solution matrix sol[N][N] */
void printSolution() {
for (int x = 0; x < N; x++) {
for (int y = 0; y < N; y++)
cout << map[x][y];
cout << endl;
}
}
/* A recursive utility function to solve Knight Tour problem */
bool knightsTourRecursive(int x, int y, int movei, int xMove[N], int yMove[N]) {
int nextX, nextY;
if (movei == N*N)
return true;
/* Try all next moves from the current coordinate x, y */
for (int k = 0; k < 8; k++) {
nextX = x + xMove[k];
nextY = y + yMove[k];
if (isSafe(nextX, nextY)) {
map[nextX][nextY] = movei;
if (knightsTourRecursive(nextX, nextY, movei+1, xMove, yMove)) // recursion
return true;
else
map[nextX][nextY] = -1; // backtracking
}
}
return false;
}
bool knightsTour() {
/* Initialization of solution matrix */
for (int x = 0; x < N; x++)
for (int y = 0; y < N; y++)
map[x][y] = -1;
/* xMove[] and yMove[] define next move of Knight.
xMove[] is for next value of x coordinate
yMove[] is for next value of y coordinate */
int xMove[8] = { 2, 1, -1, -2, -2, -1, 1, 2 };
int yMove[8] = { 1, 2, 2, 1, -1, -2, -2, -1 };
int initX = rand() % N;
int initY = rand() % N;
cout << "Starting at " << initX << " " << initY << endl;
// Since the Knight is initially at the first block
map[initX][initY] = 0;
/* explore all tours using solveKTUtil() */
if(!knightsTourRecursive(initX, initY, 1, xMove, yMove) ) {
cout << "Solution does not exist" << endl;
return false;
}
else
printSolution();
return true;
}
int main() {
srand( (unsigned) time(0));
knightsTour();
cin.get();
return 0;
}
This program seems to be absolutely correct, I cannot see a bug in this code.
However, the knight's tour IS a highly complex algorithm. Actually, the program needs to check up to 64!=1*2*3*...*64 different ways through the board. This is a number with 89 zeroes!
In many cases the backtracking will stop at an early branch, but some branches will go up forever.
If the tour starting at 0,0 is foudn so quickly, then it might either be pure chance, or the arrays xMove and yMove were cleverly initialized, such that a solution for (0,0) is found quickly.
So the problem is not your program, but it is the algorithm. I suggest you to do some research on this topic. There are many algorithms for the knight's tour which will give you a solution in more reasonable time.
I don't have enough reputation to comment, but this is more like a comment. Check here for a python implementation of Warnsdorff's Rule. Further optimizations over Warnsdorff's Rule is discussed here
I Have a problem with the mutation function within my genetic Algorithm. I can't quite see what I am doing wrong either. I've looked at this code for a while and I think the logic is correct, it's just not producing the results i want.
The problem
When i output the Binary array located in the Child Struct, If mutation has occured on any of the bits, then a random number will be changed, and not the one that should be.
for example
0000000 is the binary string
mutation has occured on the second
bit
0001000 would be the result
This section is located within the main.
for (int Child = 0; Child < ParentNumberInit; Child++)
{
cout << endl;
mutation(child[Child],Child);
}
This is the mutation function
void mutation(struct Parent Child1,int childnumber)
{
int mutation; // will be the random number generated
cout << endl << "Child " << (childnumber+1) << endl;
//loop through every bit in the binary string
for (int z = 0; z < Binscale; z++)
{
mutation = 0; // set mutation at 0 at the start of every loop
mutation = rand()%100; //create a random number
cout << "Generated number = " << mutation << endl;
//if variable mutation is smaller, mutation occurs
if (mutation < MutationRate)
{
if(Child1.binary_code[z] == '0')
Child1.binary_code[z] = '1';
else if(Child1.binary_code[z] == '1')
Child1.binary_code[z] = '0';
}
}
}
It's being outputted in the main like this
for (int childnumber = 0; childnumber < ParentNumberInit; childnumber++)
{
cout<<"Child "<<(childnumber+1)<<" Binary code = ";
for (int z = 0; z < Binscale; z ++)
{
cout<<child[childnumber].binary_code[z];
}
cout<<endl;
}
You can't throttle the multation rate this way. You need to separate the mutated bit from the probability of the mutation occuring.
for (int z = 0; z < Binscale; z++)
{
if (rand() % 100 < MutationRate)
{
// flip bit
Child1.binary_code[z] += 1;
Child1.binary_code[z] %= 2;
}
}
Even simpler way to flip bit:
Child1.binary_code[z] ^= 1;
try this:
void mutation(Parent& Child1,int childnumber)