I have tried writing this code to output an odd-order magic square based on user input of an odd number. When I enter 1 or 3, it works fine. Whenever I enter anything above that such as 5, 7, 9, 11, etc the program crashes the moment I press enter. I've reviewed my code and I can't pinpoint where the problem is. I get no error messages.
Small note: if you know what a magic square is, my algorithm here (given to us by the professor in English to translate to C++) does not output the correct values since they don't all add up to the same number.
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int n; //n = order
cout << "Enter an odd integer for the order of the Magic Square: ";
cin >> n;
cout << endl;
if(n%2 == 0) //only allows program to accept odd numbers
{
cout << "The number you have entered is not odd" << endl;
return 0;
}
int x, y; //x and y access the columns and rows of the following matrix
int magicsquare[n][n]; //creates a n by n matrix to set up magic square
int counter, square = n*n; //square is upper boundary
for(x=0; x<n; x++) //initialize all spaces in matrix with zeros
{
for(y=0; y<n; y++)
magicsquare[x][y] = 0;
}
/*Beginning of the magic square algorithm*/
x = 0, y = n/2; //initialize algorithm at the middle column of the top row
for (counter = 1; counter <= square; counter++) //magic square will contain the integers from 1 to n squared
{
magicsquare[x][y] = counter; //places current counter number at current position in the matrix or square
x--; //moves position diagonally up
y++; //and to the right
/*If a move takes you above the top row in the jth column, move to the bottom of the jth column*/
if(x<0)
x = n - 1;
/*If a move takes you outside to the right of the square in the ith row, move to the left side of the ith row*/
else if(y==n)
y = 0;
/*If a move takes you to an already filled square or if you move out of the square at the upper right
hand corner, move immediately below position of previous number*/
else if((magicsquare[x][y] != 0) || (x<0 && y==n))
{
y--; //move one space to the left back into the square
x = x+2; //move two spots down into the square and below previous number
}
}
for(x=0; x<n; x++)
{
for(y=0; y<n; y++)
cout << setw(5) << magicsquare[x][y];
cout << endl;
}
return 0;
}
I can't follow the logic in my head to know if this can ever actually happen, but in this code:
if(x<0)
x = n - 1;
/*If a move takes you outside to the right of the square in the ith row, move to the left side of the ith row*/
else if(y==n)
y = 0;
If both conditions would have been true, you won't fix up y and the next iteration you'll run off the end of the matrix.
Also note that int magicsquare[n][n]; is a compiler extension and not supported by the C++ standard, since n is not a compile time constant. You almost certainly want to use vector instead.
The following is illegal:
int magicsquare[n][n];
Did you ignore errors, or are you using a compiler that doesn't give errors at all? I suggest you to use an IDE that hints you when a mistake is made, so you can easily see your mistake. Please do not use notepad to write C++, that is horrible.
Fixed version:
int** magicsquare = new int*[n]; //creates a n by n matrix to set up magic square
for(int i = 0; i < n+1; ++i)
magicsquare[i] = new int[n];
Now, together with Mark B's hint, you will get this running up in no time.
Do not forget to cleanup magicsquare by the way using delete.
So I don't really know anything about magic squares. But I think that this is the behavior that you are trying to achieve:
for (int counter = 1, x = 0, y = (n / 2); counter <= n * n; ++counter){
magicsquare[x][y] = counter; //places current counter number at current position in the matrix or square
if (counter % n == 0){ //moves down into the square and below previous number
x = (x + 1) % n;
}
else //moves position diagonally up and to the right
{
x = (x + n - 1) % n;
y = (y + 1) % n;
}
}
Two additional points:
Until we can use the Array Extensions Technical Specification I think you should avoid declaring C99's runtime-sized arrays in your code. Even though gcc will allow it. You might look into doing something like: vector<vector<int>> magicsquare(n, vector<int>(n));
This doesn't match the behavior illustrated by Wikipedia's article but you can get there by tweaking the start values and order of indexing.
Related
I need an Algorithm that I will use to scan pixels out from the center. Problem is with different lengths and sizes, it sometimes can't get to the position (See Image below blue part).
To illustrate the problem more I will show the example output:
If you compare the pictures you will notice that it goes in a spiral and the outputs match with a regular for loop and obviously the problem that it doesn't print the blue part correctly
Here is the code:
#include<iostream>
#include<string>
#include<math.h>
int arr[] = { 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15 };
int arrSize = sizeof(arr) / sizeof(arr[0]);
int width = 5;
int height = 3;
void normal2DArray() {
int index = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
index++;
}
}
}
int convertToInex(int x, int y) {
int left = x * y; // elements to the left
int right = (width - x) * y; // elements to the right
return left + right + x;
}
void spiralArray() {
// calculate middle point, which is also the start point
int x = round((float)width / 2) - 1;
int y = round((float)height / 2) - 1;
int direction = 0; // 0=right, 1=up, 2=left, 3=down
int turnCounter = 1;
int numSteps = 1;
int step = 1;
int index;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
switch (direction) {
case 0: x++; break;
case 1: y--; break;
case 2: x--; break;
case 3: y++; break;
}
index = convertToInex(x, y);
if (step % numSteps == 0) {
direction = (direction + 1) % 4;
turnCounter++;
if (turnCounter % 2 == 0) numSteps++;
}
step++;
if (step > arrSize) break;
}
}
void main() {
std::cout << "Output of Normal 2D Array:\n";
normal2DArray();
std::cout << "\n"; // better spacing
std::cout << "Output of Spiral Array:\n";
spiralArray();
}
I tried to keep the code as simple and small as possible. It should be ready to import and use.
And yes I already searched for my answer online but I didn't find anything that covered up the problem here nor had a similar setup like I have(1D arr and combined 2D array WIDTH/HEIGHT) and for sure not in c++.
❗ Also I need a Solution that works with all widths and heights and arr sizes and also works for any side ❗
I hope you can provide me with helpful answers and would be grateful with good and fast algorithm implementations/optimizations
EDIT:
Thanks to the replies in this Thread. I decided to go with the solution from #ldog for now even though I'm not completely satisfied with it.
Here are the edited code parts:
int failcounter = 0;
while (true) {
index = convertToInex(x, y); // defines the index position in arr
if (index < 0 || index > arrSize) failcounter++;
else std::cout << std::to_string(x) << "," << std::to_string(y) << " = " << std::to_string(arr[index]) << "\n";
// unchanged code inbetween
if (step > arrSize + failcounter) break;
Based on your comment:
#Beta they don't need to connect. It just has to detect that it's outside the array size (in that case -1) and don't scan them and find the next continue point. So it would continue like this: 5, 1, 6, 11
it seems you don't care that the spiral goes "out-of-bounds". In this case, the trivial answer is, embed the shapes that have no spiral in one that is always guaranteed to have one.
Thus if your input rectangle is N x M, then embed it in a rectangle of size max(M,N) x max(M,N), solve the problem in the latter, and when printing just ignore non-existent numbers in the original problem. Your printed sequence then will always be unique up to how the embedding occurs. The most reasonable embedding would try to center the smaller rectangle as much as possible in the larger rectangle, but this is up to you.
In this case you don't need an algorithm as you can compute everything analytically if you care to do the book-keeping and figure out the formulas involved.
You can hit a dead end (meaning exit the grid) in four spots. In each case, jump to the next live pixel you would have reached, if any live cells remain.
You can do this fairly easily by keeping track of the four corners you've visited furthest from the starting pixel. Using compass coords and N for up, these are the NE, NW, SW, and SE extremes visited.
If you hit a dead end going N from the NE pixel, jump to the pixel one to the left of the NW pixel and set the movement direction to down. If that is also a dead end, jump to one below the SW pixel and set the movement direction to right. Etc... When all four corners and dead ends then you're done.
Problem description:
There's a chocolate bar that consists of m x n squares. Some of the squares are black, some are white. Someone breaks the chocolate bar along its vertical axis or horizontal axis. Then it is broken again along its vertical or horizontal axis and it's being broken until it can broken into a single square or it can broken into squares that are only black or only white. Using a preferably divide-and-conquer algorithm, find the number of methods a chocolate bar can be broken.
Input:
The first line tells you the m x n dimensions of the chocolate bar. In the next m lines there are n characters that tell you how does the chocolate bar look. Letter w is a white square, letter b is a black square.
for example:
3 2
bwb
wbw
Output:
the number of methods the chocolate bar can be broken:
for the example above, it's 5 (take a look at the attached picture).
I tried to solve it using an iterative approach. Unfortunately, I couldn't finish the code as I'm not yet sure how to divide the the halves (see my code below). I was told that an recursive approach is much easier than this, but I have no idea how to do it. I'm looking for another way to solve this problem than my approach or I'm looking for some help with finishing my code.
I made two 2D arrays, first for white squares, second for black squares. I'm making a matrix out of the squares and if there's a chocolate of such or such color, then I'm marking it as 1 in the corresponding array.
Then I made two arrays of the two cumulative sums of the matrices above.
Then I created a 4D array of size [n][m][n][m] and I made four loops: first two (i, j) are increasing the size of an rectangular array that is the size of the searching array (it's pretty hard to explain...) and two more loops (k, l) are increasing the position of my starting points x and y in the array. Then the algorithm checks using the cumulative sum if in the area starting at position kxl and ending at k+i x l+j there is one black and one white square. If there is, then I'm creating two more loops that will divide the area in half. If in the two new halves there are still black and white squares, then I'm increasing the corresponding 4D array element by the number of combinations of the first halve * the number of combinations of the second halve.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
int counter=0;
int n, m;
ifstream in;
in.open("in.txt");
ofstream out;
out.open("out.txt");
if(!in.good())
{
cout << "No such file";
return 0;
}
in >> n >> m;
int whitesarray[m][n];
int blacksarray[m][n];
int methodsarray[m][n][m][n];
for(int i=0; i<m; i++)
{
for(int j=0; j<n; j++)
{
whitesarray[i][j] = 0;
blacksarray[i][j] = 0;
}
}
while(in)
{
string colour;
in >> colour;
for (int i=0; i < colour.length(); i++)
{
if(colour[i] == 'c')
{
blacksarray[counter][i] = 1;
}
if(colour[i] == 'b')
{
whitesarray[counter][i] = 1;
}
}
counter++;
}
int whitessum[m][n];
int blackssum[m][n];
for (int i=0; i<m; i++)
{
for (int j=0; j<n; j++)
{
if(i-1 == -1 && j-1 == -1)
{
whitessum[i][j] = whitesarray[i][j];
blackssum[i][j] = blacksarray[i][j];
}
if(i-1 == -1 && j-1 != -1)
{
whitessum[i][j] = whitessum[i][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i][j-1] + blacksarray[i][j];
}
if(j-1 == -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blacksarray[i][j];
}
if(j-1 != -1 && i-1 != -1)
{
whitessum[i][j] = whitessum[i-1][j] + whitessum[i][j-1] - whitessum[i-1][j-1] + whitesarray[i][j];
blackssum[i][j] = blackssum[i-1][j] + blackssum[i][j-1] - blackssum[i-1][j-1] + blacksarray[i][j];
}
}
}
int posx=0;
int posy=0;
int tempwhitessum=0;
int tempblackssum=0;
int k=0, l=0;
for (int i=0; i<=m; i++)
{
for (int j=0; j<=n; j++) // wielkosc wierszy
{
for (posx=0; posx < m - i; posx++)
{
for(posy = 0; posy < n - j; posy++)
{
k = i+posx-1;
l = j+posy-1;
if(k >= m || l >= n)
continue;
if(posx==0 && posy==0)
{
tempwhitessum = whitessum[k][l];
tempblackssum = blackssum[k][l];
}
if(posx==0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[k][posy-1];
tempblackssum = blackssum[k][l] - blackssum[k][posy-1];
}
if(posx!=0 && posy==0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l];
}
if(posx!=0 && posy!=0)
{
tempwhitessum = whitessum[k][l] - whitessum[posx-1][l] - whitessum[k][posy-1] + whitessum[posx-1][posy-1];
tempblackssum = blackssum[k][l] - blackssum[posx-1][l] - blackssum[k][posy-1] + blackssum[posx-1][posy-1];
}
if(tempwhitessum >0 && tempblackssum > 0)
{
for(int e=0; e<n; e++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
for(int r=0; r<m; r++)
{
//Somehow divide the previously found area by two and check again if there are black and white squares in this area
}
}
}
}
}}
return 0;
}
I strongly recommend recursion for this. In fact, Dynamic Programming (DP) would also be very useful, especially for larger bars. Recursion first ...
Recursion
Your recursive routine takes a 2-D array of characters (b and w). It returns the number of ways this can be broken.
First, the base cases: (1) if it's possible to break the given bar into a single piece (see my comment above, asking for clarification), return 1; (2) if the array is all one colour, return 1. For each of these, there's only one way for the bar to end up -- the way it was passed in.
Now, for the more complex case, when the bar can still be broken:
total_ways = 0
for each non-edge position in each dimension:
break the bar at that spot; form the two smaller bars, A and B.
count the ways to break each smaller bar: count(A) and count(B)
total_ways += count(A) * count(B)
return total_ways
Is that clear enough for the general approach? You still have plenty of coding to do, but using recursion allows you to think of only the two basic ideas when writing your function: (1) How do I know when I'm done, and what trivial result do I return then? (2) If I'm not done, how do I reduce the problem?
Dynamic Programming
This consists of keeping a record of situations you've already solved. The first thing you do in the routine is to check your "data base" to see whether you already know this case. If so, return the known result instead of recomputing. This includes the overhead of developing and implementing said data base, probably a look-up list (dictionary) of string arrays and integer results, such as ["bwb", "wbw"] => 5.
I am working on a program in which I must print out the number of primes, including 1 and 239, from 1 - 239 ( I know one and or two may not be prime numbers, but we will consider them as such for this program) It must be a pretty simple program because we have only gone over some basics. So far my code is as such, which seems like decent logical flow to me, but doesnt produce output.
#include <iostream>
using namespace std;
int main()
{
int x;
int n = 1;
int y = 1;
int i = 0;
while (n<=239)
{x = n % y;
if (x = 0)
i++;
if (y < n)
y++;
n++;
while (i == 2)
cout << n;
}
return 0;
}
The way I want this to work is to take n, as long as n is 239 or less, and preform modulus division with every number from 1 leading up to n. Every time a number y goes evenly into n, a counter will be increased by 1. if the counter is equal to 2, then the number is prime and we print it to the screen. Any help would be so greatly appreciated. Thanks
std::cout << std::to_string(2) << std::endl;
for (unsigned int i = 3; i<240; i += 2) {
unsigned int j = 3;
int sq = sqrt(i);
for (; j <= sq; j += 2) if (!(i%j)) break;
if (j>sq) std::cout << std::to_string(i) << std::endl;
}
first of all, the prime definition: A prime number (or a prime) is a natural number greater than 1 that has no positive divisors other than 1 and itself.
so you can skip all the even numbers (and hence ... i+=2).
Moreover no point to try to divide for a number greater than sqrt(i), because then it will have a divisor less than sqrt(i) and the code finds that and move to the next number.
Considering only odd numbers, means that we can skip even numbers as divisors (hence ... j+=2).
In your code there are clearly beginner errors, like (x = 0) instead of x==0. but also the logic doesn't convince. I agree with #NathanOliver, you need to learn to use a debugger to find all the errors. For the rest, good luck with the studies.
lets start with common errors:
first you want to take input from user using cin
cin>>n; // write it before starting your while loop
then,
if (x = 0)
should be:
if (x == 0)
change your second while loop to:
while (i == 2){
cout << n;
i++;
}
I was solving problems on HackerRank when I got stuck at this one.
Problem Statement
You are given a 2D matrix, a, of dimension MxN and a positive integer R. You have to rotate the matrix R times and print the resultant matrix. Rotation should be in anti-clockwise direction.
Rotation of a 4x5 matrix is represented by the following figure. Note that in one rotation, you have to shift elements by one step only (refer sample tests for more clarity).
It is guaranteed that the minimum of M and N will be even.
Input
First line contains three space separated integers, M, N and R, where M is the number of rows, N is number of columns in matrix, and R is the number of times the matrix has to be rotated.
Then M lines follow, where each line contains N space separated positive integers. These M lines represent the matrix.
Output
Print the rotated matrix.
Constraints
2 <= M, N <= 300
1 <= R <= 10^9
min(M, N) % 2 == 0
1 <= aij <= 108, where i ∈ [1..M] & j ∈ [1..N]'
What I tried to do was store the circles in a 1D array. Something like this.
while(true)
{
k = 0;
for(int j = left; j <= right; ++j) {temp[k] = a[top][j]; ++k;}
top++;
if(top > down || left > right) break;
for(int i = top; i <= down; ++i) {temp[k] = a[i][right]; ++k;}
right--;
if(top > down || left > right) break;
for(int j = right; j >= left; --j) {temp[k] = a[down][j] ; ++k;}
down--;
if(top > down || left > right) break;
for(int i = down; i >= top; --i) {temp[k] = a[i][left]; ++k;}
left++;
if(top > down || left > right) break;
}
Then I could easily rotate the 1D matrix by calculating its length modulo R. But then how do I put it back in matrix form? Using a loop again would possibly cause a timeout.
Please don't provide code, but only give suggestions. I want to do it myself.
Solution Created :
#include <iostream>
using namespace std;
int main() {
int m,n,r;
cin>>m>>n>>r;
int a[300][300];
for(int i = 0 ; i < m ; ++i){
for(int j = 0; j < n ; ++j)
cin>>a[i][j];
}
int left = 0;
int right = n-1;
int top = 0;
int down = m-1;
int tleft = 0;
int tright = n-1;
int ttop = 0;
int tdown = m-1;
int b[300][300];
int k,size;
int temp[1200];
while(true){
k=0;
for(int i = left; i <= right ; ++i)
{
temp[k] = a[top][i];
// cout<<temp[k]<<" ";
++k;
}
++top;
if(top > down || left > right)
break;
for(int i = top; i <= down ; ++i)
{
temp[k]=a[i][right];
// cout<<temp[k]<<" ";
++k;
}
--right;
if(top > down || left > right)
break;
for(int i = right; i >= left ; --i)
{
temp[k] = a[down][i];
// cout<<temp[k]<<" ";
++k;
}
--down;
if(top > down || left > right)
break;
for(int i = down; i >= top ; --i)
{
temp[k] = a[i][left];
// cout<<temp[k]<<" ";
++k;
}
++left;
if(top > down || left > right)
break;
//________________________________\\
size = k;
k=0;
// cout<<size<<endl;
for(int i = tleft; i <= tright ; ++i)
{
b[ttop][i] = temp[(k + (r%size))%size];
// cout<<(k + (r%size))%size<<" ";
// int index = (k + (r%size))%size;
// cout<<index;
++k;
}
++ttop;
for(int i = ttop; i <= tdown ; ++i)
{
b[i][tright]=temp[(k + (r%size))%size];
++k;
}
--tright;
for(int i = tright; i >= tleft ; --i)
{
b[tdown][i] = temp[(k + (r%size))%size];
++k;
}
--tdown;
for(int i = tdown; i >= ttop ; --i)
{
b[i][tleft] = temp[(k + (r%size))%size];
++k;
}
++tleft;
}
size=k;
k=0;
if(top != ttop){
for(int i = tleft; i <= tright ; ++i)
{
b[ttop][i] = temp[(k + (r%size))%size];
++k;
}
++ttop;
}
if(right!=tright){
for(int i = ttop; i <= tdown ; ++i)
{
b[i][tright]=temp[(k + (r%size))%size];
++k;
}
--tright;
}
if(down!=tdown){
for(int i = tright; i >= tleft ; --i)
{
b[tdown][i] = temp[(k + (r%size))%size];
++k;
}
--tdown;
}
if(left!=tleft){
for(int i = tdown; i >= ttop ; --i)
{
b[i][tleft] = temp[(k + (r%size))%size];
++k;
}
++tleft;
}
for(int i = 0 ; i < m ;++i){
for(int j = 0 ; j < n ;++j)
cout<<b[i][j]<<" ";
cout<<endl;
}
return 0;
}
You need to break down this problem (remind me of an interview question from gg and fb) :
Solve first rotating a sequence one a single position
Then solve rotating a sequence N times
Model each "circle" or ring as an array. You may or may not actually need to store in a separate data
Iterate over each ring and apply the rotating algorithm
Lets consider the case of an array of length L which needs to be rotated R time. Observe that if R is a multiple of L, the array will be unchanged.
Observe too that rotating x times to the right is the same as rotating L - x to the left (and vice versa).
Thus you can first design an algorithm able to rotate once either left or right one exactly one position
Reduce the problem of rotating R times to the left to rotating R modulo L to the left
If you want to go further reduce the problem of rotating R modulo L to the left to rotating left R modulo L or rotating right L - R modulo L. Which means if you have 100 elements and you have to do 99 rotations left, you better do 1 rotation right and be done with it.
So the complexity will be O ( Number of circles x Circle Length x Single Rotation Cost)
With an array in-place it means O( min(N,m) * (N * M)^2 )
If you use a doubly linked list as temporary storage, a single rotation sequence is done by removing the front and putting it at the tail (or vice versa to rotate right). So what you can do is copy all data first to a linked list. Run the single rotation algorithm R modulo L times, copy back the linked list on the ring position, and move on the next right till all rings are processed.
Copy ring data to list is O(L), L <= N*M
Single Rotation Cost is O(1)
All rotations R modulo L is O(L)
Repeat on all min(N,m) rings
With a spare double linked list it means complexity of O( min(N,m) * (N * M))
I would start with a simplifying assumption: M is less than or equal to N. Thus, you are guaranteed to have an even number of rows. (What if M > N? Then transpose the matrix, carry out the algorithm, and transpose the matrix again.)
Because you have an even number of rows, you can easily find the corners of each cycle within the matrix. The outermost cycle has these corners:
a1,1 → aM,1 → aM,N → a1,N
To find the next cycle, move each corner inward, which means incrementing or decrementing the index at each corner as appropriate.
Knowing the sequence of corners allows you to iterate over each cycle and store the values in a one-dimensional vector. In each such vector a, start from index R % a.size() and increment the index a.size() - 1 times to iterate over the rotated elements of the cycle. Copy each element a[i % a.size()] back to the cycle.
Note that we don't actually rotate the vector. We accomplish the rotation by starting from an offset index when we copy elements back to the matrix. Thus, the overall running time of the algorithm is O(MN), which is optimal because it costs O(MN) just to read the input matrix.
I would treat this as a problem that divides the matrix into submatrices. You could probably write a function that shifts the matrices (and submatrices) outer rows and columns by one each time you call it. Take care to handle the four corners of the matrix appropriately.
Check this out for suggestions how to shift the columns.
Edit (more detailed):
Read each matrix circle in as a vector, use std::rotate on it R % length.vector times, write back. Maximally 150 operations.
Each element moves uniquely according to one of four formulas, adding five movements of known sizes (I'll leave the size calculation out since you wanted to figure it out):
formula (one of these four):
left + down + right + up + left
down + right + up + left + down
right + up + left + down + right
up + left + down + right + up
Since the smallest side of the matrix is even, we know there is not an element remaining in place. After R rotations, the element has circled around floor (R / formula) times but still needs to undergo extra = R % formula shifts. Once you know extra, simply calculate the appropriate placement for the element.
how do you go about solving this problem ::
A robot is located at the top-left corner of a 4x4 grid. The robot can move either up, down, left, or right, but can not visit the same spot twice. The robot is trying to reach the bottom-right corner of the grid.
My ideas:
Backtracking solution where we go through the tree of all solutions and print once we reach goal cell. I implemented that but I'm not sure if it's correct or makes sense, or if it is even the right approach. I've posted code here and would much appreciate if someone could explain what's wrong with it.
Recursive solution where I start at start cell, and find the path to the goal cell from each of its neighboring cells recursively, with the base case being hitting the goal cell.
QUESTIONS:
1) Are these two ways of expressing the same idea?
2) Do these ideas even make sense?
3) What is the time complexity of each of these solutions? I think the second one is 4^n?
4) Does my backtracking code make sense?
5) Is there a much simpler way to do this?
Here is my code, which prints the correct number of paths for N = 4. Is it correct?
#define N 4
int counter = 0;
bool legal_move(int x, int y, int array[N+2][N+2]){
bool ret = (array[x][y] == 1);
array[x][y] = 0;
return ret;
}
/*
void print_array(int array[N+2][N+2]){
for(int i = 0; i < N+2; i++){
for(int j = 0; j < N+2; j++)
cout << array[i][j] << " ";
cout << endl;
}
cout << endl << endl;
}
*/
void print_paths(int x, int y, int n, int m, int array[N+2][N+2]){
if(x == n && y == m){
print_array(array);
counter++;
}
else {
int dx = 1;
int dy = 0;
for(int i = 0; i < 4; i++){
if(legal_move(x + dx, y + dy, array)){
print_paths(x + dx, y + dy, n, m, array);
array[x+dx][y+dy] = 1;
}
swap(dx,dy);
if(i == 1)
dx = -dx;
}
}
}
int main(){
int array[N+2][N+2];
for(int i = 1; i < N+1; i++)
for(int j = 1; j < N+1; j++)
array[i][j] = 1;
for(int i = 0; i < N+2; i++)
array[0][i] = array[i][0] = array[N+1][i] = array[i][N+1] = 0;
//print_array(array);
array[1][1] = 0; //Set start cell to be seen.
print_paths(1,1,N,N,array);
cout << counter << endl;
}
I think it's the same idea.
The problem with your code is that you haven't implemented 'but can not visit the same spot twice' correctly.
Suppose that your robot has gone from S to A by some path, and you are now examining whether to go to B adjacent to A. The test should be 'has the robot been to B before on the current path'. But what you have implemented is 'has the robot visited B before on any path'.
In other words you need to modify print_paths to take an extra parameter for the current path, and use that to implement the test correctly.
Here is a partial answer, which talks mostly about complexity (I think your code is correct, after the minor bugfix suggested by john, and backtracking is probably the simplest way to do what you want).
The time complexity seems something like O(3^n^2) to me - there are at most n^2 nodes, and at each node you want to check 3 possibilities. There are actually less nodes, because of the way backtracking works, but the complexity is at least O(2^(n^2/4)), so it's greater than any exponential. (the O in the last formula is actually a theta).
The below diagram describes this lower bound. Cells marked by ? have a "decision" in them - the robot may decide to go straight or turn. There are at least n^2/4 such cells, so the number of paths is at least 2^(n^2/4).
?->-?->-?->-V
| | | | | | |
>-^ >-^ >-^ V
|
V-<-?-<-?-<-?
| | | | | | |
V ^-< ^-< ^-<
|
...