How to transform an adjacency matrix into an incidence Matrix - c++
I'm trying to transform the adjacency matrix into an incidence matrix of an undirected graph. For edges :
(1, 2), (1,5), (1,6), (2,3), (2,5), (3,4), (3,5), (4,5), (5,6)
Adj matrix is :
0 1 0 0 1 1
1 0 1 0 1 0
0 1 0 1 1 0
0 0 1 0 1 0
1 1 1 1 0 1
1 0 0 0 1 0
and I expect the result for the incidence matrix to be
0 1 0 0 1 1 0 0 0
1 0 1 0 1 0 0 0 0
0 1 0 1 1 0 0 0 0
0 0 1 0 1 0 0 0 0
1 1 1 1 0 1 0 0 0
1 0 0 0 1 0 0 0 0
but, my program returns this :
1 0 0 0 0 0 0 0 0
0 1 1 0 0 0 0 0 0
0 1 0 1 1 0 0 0 0
0 0 0 1 0 1 0 0 0
1 0 1 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0
My source code :
graph constructor
Graph(int vertices, int edges)
{
this->vertices = vertices;
this->edges = edges;
edge = std::vector<Graph::Edge*>(edges);
for (int i = 0; i < edges; i++)
{
edge[i] = new Edge(this);
}
}
Graph* g = new Graph(numberOfVertices, numberOfEdges);
g->edge[0]->src = 1;
g->edge[0]->dest = 2;
g->edge[1]->src = 1;
g->edge[1]->dest = 5;
g->edge[2]->src = 1;
g->edge[2]->dest = 6;
g->edge[3]->src = 2;
g->edge[3]->dest = 3;
g->edge[4]->src = 2;
g->edge[4]->dest = 5;
g->edge[5]->src = 3;
g->edge[5]->dest = 4;
g->edge[6]->src = 3;
g->edge[6]->dest = 5;
g->edge[7]->src = 4;
g->edge[7]->dest = 5;
g->edge[8]->src = 5;
g->edge[8]->dest = 6;
for (i = 0; i < numberOfEdges; i++)
{
adjacency_matrix[g->edge[i]->src][g->edge[i]->dest] = 1;
adjacency_matrix[g->edge[i]->dest][g->edge[i]->src] = 1;
}
std::cout << "Adjacency matrix : " << std::endl;
for (i = 1; i <= numberOfVertices; i++)
{
for (j = 1; j <= numberOfVertices; j++)
{
std::cout<<adjacency_matrix[i][j]<<" ";
}
std::cout << std::endl;
}
// Incidence Matrix
int counter = 0;
for( int i = 1; i <= numberOfEdges; i++){
for(int j = i + 1; j < numberOfVertices; j++ ){
if(adjacency_matrix[i][j] == 1){
incidence_matrix[i][counter] = 1;
incidence_matrix[j][counter] = 1;
++counter;
}
}
}
for( int i = 1; i <= numberOfVertices; i++){
for(int j = 1; j <= numberOfEdges; j++){
std::cout<<incidence_matrix[i][j]<<" ";
}
std::cout<<std::endl;
}
The ideas in the code are correct. But the indexing in the array is wrong.
Indexing should start at 0. Note: this also applies when setting up the adjacency matrix.
The numbers you use to name the vertices/nodes where originally 1,2,3,4,5,6. I propose to call them 0,1,2,3,4,5. Your original edge (1,2) then becomes (0,1). But if we consistently rename all the vertices everywhere we end up with the same graph. The advantage of this new naming convention is that we can use these names directly as indices in the C++ data structures you are using. (Provided we use the corresponding integer value and not consider these names to be strings.)
The specification of the Graph becomes
Graph* g = new Graph(numberOfVertices, numberOfEdges);
g->edge[0]->src = 0;
g->edge[0]->dest = 1;
g->edge[1]->src = 0;
g->edge[1]->dest = 4;
g->edge[2]->src = 0;
g->edge[2]->dest = 5;
g->edge[3]->src = 1;
g->edge[3]->dest = 2;
g->edge[4]->src = 1;
g->edge[4]->dest = 4;
g->edge[5]->src = 2;
g->edge[5]->dest = 3;
g->edge[6]->src = 2;
g->edge[6]->dest = 4;
g->edge[7]->src = 3;
g->edge[7]->dest = 4;
g->edge[8]->src = 4;
g->edge[8]->dest = 5;
So printing the adjacency matrix becomes:
std::cout << "Adjacency matrix : " << std::endl;
for (i = 0; i < numberOfVertices; i++)
{
for (j = 0; j < numberOfVertices; j++)
{
std::cout<<adjacency_matrix[i][j]<<" ";
}
std::cout << std::endl;
}
and the calculation of the incidence matrix becomes:
// Incidence Matrix
int counter = 0;
for( int i = 0; i < numberOfVertices; i++){ //numberOfVertices!!
for(int j = i + 1; j < numberOfVertices; j++ ){
if(adjacency_matrix[i][j] == 1){
incidence_matrix[i][counter] = 1;
incidence_matrix[j][counter] = 1;
++counter;
}
}
}
for( int i = 0; i < numberOfVertices; i++){
for(int j = 0; j < numberOfEdges; j++){
std::cout<<incidence_matrix[i][j]<<" ";
}
std::cout<<std::endl;
}
Note that the order of the edges is determined now by the order in which you traverse the adjacency matrix.
Related
C++ display possible bishop moves in an empty chess board
This task asks to display possible bishop moves in a chessboard (8 x 8) as in an example shown below: x = 4, y = 4 1 0 0 0 0 0 1 0, 0 1 0 0 0 1 0 0, 0 0 1 0 1 0 0 0, 0 0 0 2 0 0 0 0, 0 0 1 0 1 0 0 0, 0 1 0 0 0 1 0 0, 1 0 0 0 0 0 1 0, 0 0 0 0 0 0 0 1 Image for clear understanding #include <iostream> using namespace std; int main() { int array[8][8], x , y; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { array[i][j] = 0; } } cout << "Input x coordinate: "; cin >> x; cout << "Input y coordinate: "; cin >> y; for (int i = 0; i < 8; i++) { // 1st diagonal array[x + i][y + i] = 1; array[x - i][y - i] = 1; } for (int i = 0; i < 8; i++) { // 2nd diagonal array[x + i][y - i] = 1; array[x - i][y + i] = 1; } array[x][y] = 2; for (int i = 0; i < 8; i++) //Cout { for (int j = 0; j < 8; j++) { cout << array[i][j]; } cout << endl; } return 0; } It seems to work only with 1st diagonal
This is more of an algorithm/math answer than C++. Suppose the grid's bottom left point is the origin (i.e. i = 0, j = 0), and the coordinate of the top right point in the grid is i=7, j=7. A bishop that is on i=0, j=0 can hit anything on these two lines: i = j and i = - j When you put the bishop at point x, y instead of 0,0, these lines change to: i - x = j - y and i - x = - (j - y) Now, you can iterate all points in the matrix and check which ones satisfy the line equation: int main() { int x, y; std::cout << "Input x coordinate: "; std::cin >> x; std::cout << "Input y coordinate: "; std::cin >> y; int array[8][8]; for (int i = 0; i < 8; i++) { for (int j = 0; j < 8; j++) { if ((i - x == j - y) || (i - x == -(j - y))) { array[i][j] = 1; } else { array[i][j] = 0; } } } array[x][y] = 2; // We should print the matrix from top to bottom. // j represents the y coordinate, and i represents the x coordinate. for (int j = 7; j >= 0; j--) { for (int i = 0; i < 8; i++) { std::cout << array[i][j]; } std::cout << std::endl; } return 0; }
It looks like it's working for both diagonals when I run it. There is a small bug that might mess things up though. You'll want to add bounds checks like this: for (int i = 0; i < 8; i++) { // 1st diagonal if (x + i < 8 && y + i < 8) array[x + i][y + i] = 1; if (x - i >= 0 && y - i >= 0) array[x - i][y - i] = 1; } for (int i = 0; i < 8; i++) { // 2nd diagonal if (x + i < 8 && y - i >= 0) array[x + i][y - i] = 1; if (x - i >= 0 && y + i < 8) array[x - i][y + i] = 1; } Without these bounds checks you'll be accessing elements outside of the array bounds and could be messing up other entries in the array. There are other ways to do the bounds checking, but this might be the easiest. To illustrate the issue, assume x = 4 and then in the for loop when i = 5. When you're indexing into the array with array[x - i] that'll be the same as array[-1]. When you index into an array with a negative value you'll be messing with the wrong memory.
I would start with a very simple case. Suppose we want to plot the diagonal matrix of size 4x4: i 0 1 2 3 j 0 1 0 0 0 1 0 1 0 0 2 0 0 1 0 3 0 0 0 1 We have a non zero value when: i = j (I) Now, suppose we shift this diagonal horizontally so that the non-zero value of the first line is located at X0. For example, for X0 = 1: X0 i' 0 1 2 3 j' 0 0 1 0 0 1 0 0 1 0 2 0 0 0 1 3 0 0 0 0 The shifted coordinates are: i' = i + X0 (II) Doing the same for shifting vertically by Y0: j' = j + Y0 (III) With (II) and (III) in (I) we have: i' - X0 = j' - Y0 (IV) Now we do the same for the antidiagonal matrix: i 0 1 2 3 j 0 0 0 0 1 1 0 0 1 0 2 0 1 0 0 3 1 0 0 0 We have a non zero value when: j = 3 - i (V) Shifting horizontally by X0 we have: i' = -3 + i + X0 (VI) Shifting vertically by Y0: j' = j + Y0 (VII) With (VI) and (VII) in (V): j' - Y0 = X0 - i' (VIII) The code just needs to check for (IV) and (VIII): #include <iostream> using namespace std; int main() { int array[8][8] = {0,}; int x = 0; int y = 0; cout << "Input x coordinate: "; cin >> x; cout << "Input y coordinate: "; cin >> y; for (int j = 0; j < 8; j++) for (int i = 0; i < 8; i++) if ( i - x == j - y || j - y == x - i) array[j][i] = 1; array[y][x] = 2; for (int j = 0; j < 8; j++) { for (int i = 0; i < 8; i++) cout << array[j][i]; cout << endl; } return 0; } Note that the matrix is plotted following the convention array[lines][columns], so to set cartesian coordinates we write array[y][x].
Generate all undirected graphs with n nodes
I'm trying to generate all the undirected graphs with n nodes, using recursive backtracking. I have to write their matrix (I don't know how is it called in english - in my language it would be adjacent matrix - is that right?) into a file. For example: input 3 output 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 1 1 1 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 1 0 1 1 1 0 Here is my program: #include <iostream> #include <fstream> using namespace std; ifstream f("gengraf.in"); ofstream g("gengraf.out"); int st[100], n, adiacenta[100][100], l=1; void tipar(int k) { for (int i = 1; i < k; i++) { for (int j = i+1; j < k; j++) { adiacenta[i][j] = adiacenta[j][i] = st[l]; } l++; } for (int i = 1; i < k; i++) { for (int j = 1; j < k; j++) { g << adiacenta[i][j] << " "; } g << endl; } } int valid(int k) { return 1; } void back(int k) { if (k == ((n - 1) * n / 2) + 1) { l = 1; tipar(k); g << endl; } else { for (int i = 0; i <= 1; i++) { st[k] = i; if (valid(k)) { back(k + 1); } } } } int main() { f >> n; g << pow(2, (n * (n - 1))/2); g << endl; back(1); } but my output is: 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 0 0 1 1 1 0 0 1 0 0 0 1 1 1 0 1 1 1 0 0 1 1 1 0 1 1 1 0 and I don't know how to fix that. I see why does happen - I generate 2^(n*(n-1))/2) graphs (because that's how many undirected graphs with n nodes are), and instead of generating 8 distinct ones, I get only 4 distinct ones, shown 2 times. That is (I suppose) because my program outputs a graph with, let's say, a link between the node 1 and 3 and another graph with a link between the node 3 and 1. And that is basically the same undirected graph. So if I am right, I should make my program not show each graph twice and it should work. So basically I have to get rid of each graph with the "reversed" node (so if I got one with a link between 1 and 3, I shouldn't get another one with a link between 3 and 1 because they are the same). Am I right? If so, how can I do that? Thanks.
Problems with your code: Value of l in tipar() id not increased after assignment. Size of adjacency matrix is n * n not k * k. This code work as expected. #include <iostream> #include <fstream> using namespace std; ifstream f("gengraf.in"); ofstream g("gengraf.out"); int st[100], n, adiacenta[100][100], l=1; int pow(int a, int b) { int r = 1; while (b) { if (b&1) r *= a; b >>= 1; a *= a; } return r; } void tipar() { for (int i = 1; i <= n; i++) { for (int j = i+1; j <= n; j++) { adiacenta[i][j] = adiacenta[j][i] = st[l]; l++; } } for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { g << adiacenta[i][j] << " "; } g << endl; } } int valid(int k) { return 1; } void back(int k) { if (k == (n * (n-1) / 2) + 1) { l = 1; tipar(); g << endl; } else { for (int i = 0; i <= 1; i++) { st[k] = i; if (valid(k)) { back(k+1); } } } } int main() { cin >> n; g << pow(2, (n * (n - 1))/2); g << endl; back(1); }
Fill 2-dimensional array with zeros by flipping groups of cells
There is a problem where I need to fill an array with zeros, with the following assumptions: in the array there can only be 0 and 1 we can only change 0 to 1 and 1 to 0 when we meet 1 in array, we have to change it to 0, such that its neighbours are also changed, for instance, for the array like the one below: 1 0 1 1 1 1 0 1 0 When we change element at (1,1), we then got the array like this: 1 1 1 0 0 0 0 0 0 We can't change the first row We can only change the elements that are in the array The final result is the number of times we have to change 1 to 0 to zero out the array 1) First example, array is like this one below: 0 1 0 1 1 1 0 1 0 the answer is 1. 2) Second example, array is like this one below: 0 1 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 The answer is 10. There also can be situations that its impossible to zero out the array, then the answer should be "impossible". Somehow I can't get this working: for the first example, I got the right answer (1) but for the second example, program says impossible instead of 10. Any ideas what's wrong in my code? #include <iostream> using namespace std; int main(int argc, char **argv) { int n,m; cin >> n >> m; bool tab[n][m]; for(int i=0; i<n; i++) for(int j=0; j<m; j++) cin >> tab[i][j]; int counter = 0; for(int i=0; i<n-1; i++) { for(int j=0; j<m-1; j++) { if(tab[i][j] == 1 && i > 0 && j > 0) { tab[i-1][j] = !tab[i-1][j]; tab[i+1][j] = !tab[i+1][j]; tab[i][j+1] = !tab[i][j+1]; tab[i][j-1] = !tab[i][j-1]; tab[i][j] = !tab[i][j]; counter ++; } } } bool impossible = 0; for(int i=0; i<n; i++) { for(int j=0; j<m; j++) { if(tab[i][j] == 1) { cout << "impossible\n"; impossible = 1; break; } } if(impossible) break; } if(!impossible) cout << counter << "\n"; return 0; }
I believe that the reason your program was returning impossible in the 6x8 matrix is because you have been traversing in a left to right / top to bottom fashion, replacing every instance of 1 you encountered with 0. Although this might have seemed as the right solution, all it did was scatter the 1s and 0s around the matrix by modifying it's neighboring values. I think that the way to approach this problem is to start from bottom to top/ right to left and push the 1s towards the first row. In a way cornering (trapping) them until they can get eliminated. Anyway, here's my solution to this problem. I'm not entirely sure if this is what you were going after, but I think it does the job for the three matrices you provided. The code is not very sophisticated and it would be nice to test it with some harder problems to see if it truly works. #include <iostream> static unsigned counter = 0; template<std::size_t M, std::size_t N> void print( const bool (&mat) [M][N] ) { for (std::size_t i = 0; i < M; ++i) { for (std::size_t j = 0; j < N; ++j) std::cout<< mat[i][j] << " "; std::cout<<std::endl; } std::cout<<std::endl; } template<std::size_t M, std::size_t N> void flipNeighbours( bool (&mat) [M][N], unsigned i, unsigned j ) { mat[i][j-1] = !(mat[i][j-1]); mat[i][j+1] = !(mat[i][j+1]); mat[i-1][j] = !(mat[i-1][j]); mat[i+1][j] = !(mat[i+1][j]); mat[i][j] = !(mat[i][j]); ++counter; } template<std::size_t M, std::size_t N> bool checkCornersForOnes( const bool (&mat) [M][N] ) { return (mat[0][0] || mat[0][N-1] || mat[M-1][0] || mat[M-1][N-1]); } template<std::size_t M, std::size_t N> bool isBottomTrue( bool (&mat) [M][N], unsigned i, unsigned j ) { return (mat[i+1][j]); } template<std::size_t M, std::size_t N> bool traverse( bool (&mat) [M][N] ) { if (checkCornersForOnes(mat)) { std::cout<< "-Found 1s in the matrix corners." <<std::endl; return false; } for (std::size_t i = M-2; i > 0; --i) for (std::size_t j = N-2; j > 0; --j) if (isBottomTrue(mat,i,j)) flipNeighbours(mat,i,j); std::size_t count_after_traversing = 0; for (std::size_t i = 0; i < M; ++i) for (std::size_t j = 0; j < N; ++j) count_after_traversing += mat[i][j]; if (count_after_traversing > 0) { std::cout<< "-Found <"<<count_after_traversing<< "> 1s in the matrix." <<std::endl; return false; } return true; } #define MATRIX matrix4 int main() { bool matrix1[3][3] = {{1,0,1}, {1,1,1}, {0,1,0}}; bool matrix2[3][3] = {{0,1,0}, {1,1,1}, {0,1,0}}; bool matrix3[5][4] = {{0,1,0,0}, {1,0,1,0}, {1,1,0,1}, {1,1,1,0}, {0,1,1,0}}; bool matrix4[6][8] = {{0,1,0,0,0,0,0,0}, {1,1,1,0,1,0,1,0}, {0,0,1,1,0,1,1,1}, {1,1,0,1,1,1,0,0}, {1,0,1,1,1,0,1,0}, {0,1,0,1,0,1,0,0}}; std::cout<< "-Problem-" <<std::endl; print(MATRIX); if (traverse( MATRIX ) ) { std::cout<< "-Answer-"<<std::endl; print(MATRIX); std::cout<< "Num of flips = "<<counter <<std::endl; } else { std::cout<< "-The Solution is impossible-"<<std::endl; print(MATRIX); } } Output for matrix1: -Problem- 1 0 1 1 1 1 0 1 0 -Found 1s in the matrix corners. -The Solution is impossible- 1 0 1 1 1 1 0 1 0 Output for matrix2: -Problem- 0 1 0 1 1 1 0 1 0 -Answer- 0 0 0 0 0 0 0 0 0 Num of flips = 1 Output for matrix3: -Problem- 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 0 0 1 1 0 -Found <6> 1s in the matrix. -The Solution is impossible- 0 1 1 0 1 0 1 1 0 0 0 0 0 0 0 1 0 0 0 0 Output for matrix4 (which addresses your original question): -Problem- 0 1 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 -Answer- 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 Num of flips = 10
Ok, here comes my somewhat different attempt. Idea Note: I assume here that "We can't change the first row" means "We can't change the outmost row". Some terminology: With toggling a bit I mean changing it's value from 0 to 1 or 1 to 0. With flipping a bit I mean toggling said bit and the 4 bits around it. The act of toggling a bit is commutative. That is, it does not matter in what order we toggle it—the end result will always be the same (this is a trivial statement). This means that flipping is also a commutative action, and we are free to flip bits in any order we like. The only way to toggle a value on the edge of the matrix is by flipping the bit right next to it an uneven amount of times. As we're looking for the lowest possible flips, we want to flip it a maximum of 1 time. So, in a scenario like the on below, x will need to be flipped exactly once, and y will need to be flipped exactly 0 times. . . 1 x 0 y . , From this we can draw two conclusions: A corner of the matrix can never be toggled—if a 1 on the corner is found it is not possible with any number of flips to make the matrix zero. Your first example can thus be discarded without even flipping a single bit. A bit next to a corner must have the same same value as the bit on the other side. This matrix that you posted in a comment can thus as well be discarded without flipping a single bit (bottom right corner). Two examples of the conditions above: 0 1 . 0 x . . . . Not possible, as x needs to be flipped exactly once and exactly zero times. 0 1 . 1 x . . . . Possible, x needs to be flipped exactly once. Algorithm We can now make an recursive argument, and I propose the following: We are given an m by n matrix. Check the corner conditions above as stated above (i.e. corner != 1, bits next to corner has to be the same value). If either criteria are violated, return impossible. Go around the edge of the matrix. If a 1 is encountered, flip the closest bit inside, and add 1 to the counter. Restart now from #1 with a m - 2 by n - 2 matrix (top and bot row removed, left and right column) if either dimension is > 2, otherwise print the counter and quit. Implementation Initially I had thought this would turn out nice and pretty, but truth be told it is a little more cumbersome than I originally thought it would be as we have to keep track of a lot of indices. Please ask questions if you're wondering about the implementation, but it is in essence a pure translation of the steps above. #include <iostream> #include <vector> using Matrix = std::vector<std::vector<int>>; void flip_bit(Matrix& mat, int i, int j, int& counter) { mat[i][j] = !mat[i][j]; mat[i - 1][j] = !mat[i - 1][j]; mat[i + 1][j] = !mat[i + 1][j]; mat[i][j - 1] = !mat[i][j - 1]; mat[i][j + 1] = !mat[i][j + 1]; ++counter; } int flip(Matrix& mat, int n, int m, int p = 0, int counter = 0) { // I use p for 'padding', i.e. 0 means the full array, 1 means the outmost edge taken away, 2 the 2 most outmost edges, etc. // max indices of the sub-array int np = n - p - 1; int mp = m - p - 1; // Checking corners if (mat[p][p] || mat[np][p] || mat[p][mp] || mat[np][mp] || // condition #1 (mat[p + 1][p] != mat[p][p + 1]) || (mat[np - 1][p] != mat[np][p + 1]) || // condition #2 (mat[p + 1][mp] != mat[p][mp - 1]) || (mat[np - 1][mp] != mat[np][mp - 1])) return -1; // We walk over all edge values that are *not* corners and // flipping the bit that are *inside* the current bit if it's 1 for (int j = p + 1; j < mp; ++j) { if (mat[p][j]) flip_bit(mat, p + 1, j, counter); if (mat[np][j]) flip_bit(mat, np - 1, j, counter); } for (int i = p + 1; i < np; ++i) { if (mat[i][p]) flip_bit(mat, i, p + 1, counter); if (mat[i][mp]) flip_bit(mat, i, mp - 1, counter); } // Finished or flip the next sub-array? if (np == 1 || mp == 1) return counter; else return flip(mat, n, m, p + 1, counter); } int main() { int n, m; std::cin >> n >> m; Matrix mat(n, std::vector<int>(m, 0)); for (int i = 0; i < n; ++i) { for (int j = 0; j < m; ++j) { std::cin >> mat[i][j]; } } int counter = flip(mat, n, m); if (counter < 0) std::cout << "impossible" << std::endl; else std::cout << counter << std::endl; } Output 3 3 1 0 1 1 1 1 0 1 0 impossible 3 3 0 1 0 1 1 1 0 1 0 1 6 8 0 1 0 0 0 0 0 0 1 1 1 0 1 0 1 0 0 0 1 1 0 1 1 1 1 1 0 1 1 1 0 0 1 0 1 1 1 0 1 0 0 1 0 1 0 1 0 0 10 4 6 0 1 0 0 1 0 1 0 1 1 0 1 1 1 1 0 1 1 1 0 impossible
If tab[0][j] is 1, you have to toggle tab[1][j] to clear it. You then cannot toggle row 1 without unclearing row 0. So it seems like a reduction step. You repeat the step until there is one row left. If that last row is not clear by luck, my intuition is that it's the "impossible" case. #include <memory> template <typename Elem> class Arr_2d { public: Arr_2d(unsigned r, unsigned c) : rows_(r), columns_(c), data(new Elem[rows_ * columns_]) { } Elem * operator [] (unsigned row_idx) { return(data.get() + (row_idx * columns_)); } unsigned rows() const { return(rows_); } unsigned columns() const { return(columns_); } private: const unsigned rows_, columns_; std::unique_ptr<Elem []> data; }; inline void toggle_one(bool &b) { b = !b; } void toggle(Arr_2d<bool> &tab, unsigned row, unsigned column) { toggle_one(tab[row][column]); if (column > 0) toggle_one(tab[row][column - 1]); if (row > 0) toggle_one(tab[row - 1][column]); if (column < (tab.columns() - 1)) toggle_one(tab[row][column + 1]); if (row < (tab.rows() - 1)) toggle_one(tab[row + 1][column]); } int solve(Arr_2d<bool> &tab) { int count = 0; unsigned i = 0; for ( ; i < (tab.rows() - 1); ++i) for (unsigned j = 0; j < tab.columns(); ++j) if (tab[i][j]) { toggle(tab, i + 1, j); ++count; } for (unsigned j = 0; j < tab.columns(); ++j) if (tab[i][j]) // Impossible. return(-count); return(count); } unsigned ex1[] = { 0, 1, 0, 1, 1, 1, 0, 1, 0 }; unsigned ex2[] = { 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0 }; Arr_2d<bool> load(unsigned rows, unsigned columns, const unsigned *data) { Arr_2d<bool> res(rows, columns); for (unsigned i = 0; i < rows; ++i) for (unsigned j = 0; j < columns; ++j) res[i][j] = !!*(data++); return(res); } #include <iostream> int main() { { Arr_2d<bool> tab = load(3, 3, ex1); std::cout << solve(tab) << '\n'; } { Arr_2d<bool> tab = load(6, 8, ex2); std::cout << solve(tab) << '\n'; } return(0); }
The problem is stated like this: y yxy If you flip x, then you have to flip all the ys y But it's easy if you think about it like this: x yyy If you flip x, then you have to flip all the ys y It's the same thing, but now the solution is obvious -- You must flip all the 1s in row 0, which will flip some bits in rows 1 and 2, then you must flip all the 1s in row 1, etc, until you get to the end.
If this is indeed the Lights Out game, then there are plenty of resources that detail how to solve the game. It is also quite likely that this is a duplicate of Lights out game algorithm, as has already been mentioned by other posters. Let's see if we can't solve the first sample puzzle provided, however, and at least present a concrete description of an algorithm. The initial puzzle appears to be solvable: 1 0 1 1 1 1 0 1 0 The trick is that you can clear 1's in the top row by changing the values in the row underneath them. I'll provide coordinates by row and column, using a 1-based offset, meaning that the top left value is (1, 1) and the bottom right value is (3, 3). Change (2, 1), then (2, 3), then (3, 2). I'll show the intermediate states of the board with the * for the cell being changed in the next step. 1 0 1 (2,1) 0 0 1 (2,3) 0 0 0 (3, 2) 0 0 0 * 1 1 ------> 0 0 * ------> 0 1 0 ------> 0 0 0 0 1 0 1 1 0 1 * 1 0 0 0 This board can be solved, and the number of moves appears to be 3. The pseudo-algorithm is as follows: flipCount = 0 for each row _below_ the top row: for each element in the current row: if the element in the row above is 1, toggle the element in this row: increment flipCount if the board is clear, output flipCount if the board isnt clear, output "Impossible" I hope this helps; I can elaborate further if required but this is the core of the standard lights out solution. BTW, it is related to Gaussian Elimination; linear algebra crops up in some odd situations :) Finally, in terms of what is wrong with your code, it appears to be the following loop: for(int i=0; i<n-1; i++) { for(int j=0; j<m-1; j++) { if(tab[i][j] == 1 && i > 0 && j > 0) { tab[i-1][j] = !tab[i-1][j]; tab[i+1][j] = !tab[i+1][j]; tab[i][j+1] = !tab[i][j+1]; tab[i][j-1] = !tab[i][j-1]; tab[i][j] = !tab[i][j]; counter ++; } } } Several issues occur to me, but first assumptions again: i refers to the ith row and there are n rows j refers to the jth column and there are m columns I'm now referring to indices that start from 0 instead of 1 If this is the case, then the following is observed: You could run your for i loop from 1 instead of 0, which means you no longer have to check whether i > 0 in the if statement You should drop the for j > 0 in the if statement; that check means that you can't flip anything in the first column You need to change the n-1 in the for i loop as you need to run this for the final row You need to change the m-1 in the for j loop as you need to run this for the final column (see point 2 also) You need to check the cell in the row above the current row, so you you should be checking tab[i-1][j] == 1 Now you need to add bounds tests for j-1, j+1 and i+1 to avoid reading outside valid ranges of the matrix Put these together and you have: for(int i=1; i<n; i++) { for(int j=0; j<m; j++) { if(tab[i-1][j] == 1) { tab[i-1][j] = !tab[i-1][j]; if (i+1 < n) tab[i+1][j] = !tab[i+1][j]; if (j+1 < m) tab[i][j+1] = !tab[i][j+1]; if (j > 0) tab[i][j-1] = !tab[i][j-1]; tab[i][j] = !tab[i][j]; counter ++; } } }
A little class that can take as a input file or test all possible combination for first row with only zeros, on 6,5 matrix: #include <iostream> #include <fstream> #include <vector> #include <string> #include <cstdlib> #include <ctime> typedef std::vector< std::vector<int> > Matrix; class MatrixCleaner { public: void swapElement(int row, int col) { if (row >= 0 && row < (int)matrix.size() && col >= 0 && col < (int)matrix[row].size()) matrix[row][col] = !matrix[row][col]; } void swapElements(int row, int col) { swapElement(row - 1, col); swapElement(row, col - 1); swapElement(row, col); swapElement(row, col + 1); swapElement(row + 1, col); } void printMatrix() { for (auto &v : matrix) { for (auto &val : v) { std::cout << val << " "; } std::cout << "\n"; } } void loadMatrix(std::string path) { std::ifstream fileStream; fileStream.open(path); matrix.resize(1); bool enconteredNumber = false; bool skipLine = false; bool skipBlock = false; for (char c; fileStream.get(c);) { if (skipLine) { if (c != '*') skipBlock = true; if (c != '\n') continue; else skipLine = false; } if (skipBlock) { if (c == '*') skipBlock = false; continue; } switch (c) { case '0': matrix.back().push_back(0); enconteredNumber = true; break; case '1': matrix.back().push_back(1); enconteredNumber = true; break; case '\n': if (enconteredNumber) { matrix.resize(matrix.size() + 1); enconteredNumber = false; } break; case '#': if(!skipBlock) skipLine = true; break; case '*': skipBlock = true; break; default: break; } } while (matrix.size() > 0 && matrix.back().empty()) matrix.pop_back(); fileStream.close(); } void loadRandomValidMatrix(int seed = -1) { //Default matrix matrix = { { 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 setNum = seed; if(seed < 0) if(seed < -1) setNum = std::rand() % -seed; else setNum = std::rand() % 33554432; for (size_t r = 1; r < matrix.size(); r++) for (size_t c = 0; c < matrix[r].size(); c++) { if (setNum & 1) swapElements(r, c); setNum >>= 1; } } bool test() { bool retVal = true; for (int i = 0; i < 33554432; i++) { loadRandomValidMatrix(i); if( (i % 1000000) == 0 ) std::cout << "i= " << i << "\n"; if (clean() < 0) { // std::cout << "x"; std::cout << "\n" << i << "\n"; retVal = false; break; } else { // std::cout << "."; } } return retVal; } int clean() { int numOfSwaps = 0; try { for (size_t r = 1; r < matrix.size(); r++) { for (size_t c = 0; c < matrix[r].size(); c++) { if (matrix.at(r - 1).at(c)) { swapElements(r, c); numOfSwaps++; } } } } catch (...) { return -2; } if (!matrix.empty()) for (auto &val : matrix.back()) { if (val == 1) { numOfSwaps = -1; break; } } return numOfSwaps; } Matrix matrix; }; int main(int argc, char **argv) { std::srand(std::time(NULL)); MatrixCleaner matrixSwaper; if (argc > 1) { matrixSwaper.loadMatrix(argv[argc - 1]); std::cout << "intput:\n"; matrixSwaper.printMatrix(); int numOfSwaps = matrixSwaper.clean(); std::cout << "\noutput:\n"; matrixSwaper.printMatrix(); if (numOfSwaps > 0) std::cout << "\nresult = " << numOfSwaps << " matrix is clean now " << std::endl; else if (numOfSwaps == 0) std::cout << "\nresult = " << numOfSwaps << " nothing to clean " << std::endl; else std::cout << "\nresult = " << numOfSwaps << " matrix cannot be clean " << std::endl; } else { std::cout << "Testing "; if (matrixSwaper.test()) std::cout << " PASS\n"; else std::cout << " FAIL\n"; } std::cin.ignore(); return 0; }
changing for loop to block parition
I want to change the for-loop to block scheme I have this for loop that does this: let say n = 8 and node = 4 n: [1][2][3][4][5][6][7][8] id: 0 1 2 3 0 1 2 3 id = 0; while (id < node){ for (i = id + 1; i <= n; i = i + node) { //do stuff here id = i; }enter code here id+1; }//end while and i want it to do this: n = 8 node= 4 n: [1][2][3][4][5][6][7][8] id: 0 0 1 1 2 2 3 3 n = 16 node = 4 n: [1][2][3][4][5][6][7][8] ... [13][14][15][16] id: 0 0 0 0 1 1 1 1 ... 3 3 3 3 n = 8 node= 2 n: [1][2][3][4][5][6][7][8] id: 0 0 0 0 1 1 1 1 where each id is assign to the top n show in examples I have this but it only works for the specific scenario n= 8 & node = 4 ... b = id + 1 for (i = n-(n-(id+b)); i <= (n-(n-(id+b))+1); i+= 1) ...
I perhaps misunderstood your question but this gives the output for id as you described: for (int i = 0; i < n; i++) { id = i / (n / node); // do stuff } I use n starting from 0, but if you start from 1, just adjust the calculation by ofsetting everything to n-1.
Try this code: int node = 4; int n = 16; for (id = 0; id < node; id++) { for(int j = 0; j < n / node; j++) { //do some stuff } } Or you can use this code: int node = 4; int n = 16; for (int i = 0; i < node; i++) { id = i; for(int j = 0; j < n / node; j++) { //do some stuff } } They do the same.
Compute next hop routing table from adjacency matrix using Dijkstra's algorithm - alg. not stopping
I am trying to determine a next hop routing table using an adjacency matrix. Each node knows the full adjacency matrix for that topology. I have found previous posts explaining how to do it, however, I don't understand why mine is wrong. I have a couple of helper functions but their names are intuitive so you could skip to " starting routing calculations". I use the adjacency matrix as a cost matrix, it just has only 0's and 1's. The algorithm seems not to stop for some reason. The queue gets stuck on size 1,3 or 5 depending on node. The variable rank holds the current node index, it is run in OpenMPI so each process(rank / node) runs this chunk of code independently. Variable matrix holds the adjacency matrix. Here is the topology I am using : 0 / \ 1 2 / / | \ / \ 3 4 5 6 7 8 / \ | 9 10 11 Adjacency matrix : (As seen by Node 3, one of those that does not stop ); 1 1 1 0 0 0 0 0 0 0 0 0 1 0 0 1 1 1 1 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 My code so far: int isFull(int *d, int size) { int i; for(i = 0; i < size; i++) { if(d[i] == INF) { return -1; } } return 1; } int vecSize(int *d, int size) { int counter = 0; int i; for(i = 0; i < size; i++) { if(d[i] != INF) { counter++; } } return counter; } bool List_contains(std::list<int > l, int val) { for (std::list<int>::const_iterator iterator = l.begin(), end = l.end(); iterator != end; ++iterator) { if (*iterator == val) { return true; } } return false; } int minimum (int a, int b) { if (a < b) { return a; } return b; } /* matrix is the complete adjacency matrix */ /* starting routing calculations * */ std::list <int > visited; int *dist; dist = (int*) calloc(size, sizeof(int)); visited.push_back(rank); //debug //printf("debug not empty %d\n", isFull(dist, size)); for(i = 0; i < size; i++) { if(matrix[rank][i] == 1) { dist[i] = 1; } else { dist[i] = INF; } } dist[rank] = 0; int min; while(isFull(dist,size) < 0) { if(rank == 3) printf("node - %d -debug -- list size %d\n",rank, vecSize(dist, size)); //get the first node that isn't contained for(i = 0; i < size; i++) { if (!List_contains(visited, i) && min != rank) { min = i; break; } } for(i = 0; i < size; i++) { if((min >= dist[i]) && (!List_contains(visited, i)) && min != rank) { min = i; } } if(rank == 3) printf("min = %d\n", min); visited.push_back(min); for(i = 0; i < size; i++) { if((matrix[min][i] == 1) && (!List_contains(visited, i))) { dist[i] = minimum (dist[i], dist[min] + matrix[min][i]); } } if(rank == 3) //printf("rank %d dist = \n", rank); for(i = 0; i < size; i++) { if(rank == 3) printf("%d ", dist[i]); } if(rank == 3) printf("\n"); } /* * finished routing calculations. */ This would be the output so far : http://pastebin.com/x5wjKkyn Could someone point out what am I doing wrong? Thank you ! Later edit: Technically, the algorithm provides the correct distances, it just doesn't stop. ( The output is exclusively from node 0) Later edit: it seems that the program is not stopping because for some nodes the algo doesn't finish.