I found a bug in my code and can't figuring out the error. I tried debugging by showing the output of each variable step by step but I can't find my error. Here is what I have and what I want to do:
I have a matrix A:
0000
0101
1010
1111
And I have a matrix B:
10000
21000
30100
41100
20010
21010
40110
41110
30001
41001
30101
41101
40011
41011
40111
41111
The matrix B has 16 rows and 5 coloumns. The matrix A has 4 rows and 4 coloumns. Now I declare a matrix C that has 4 rows and 16 coloumns.
What I want to do is to calculate the inner product of each row from B with a corresponding row from A. With corresponding I mean that the first coloumn of B shoud define the row from A that I want to multiply. So the B matrix has in fact also four-dimensional vectors and the first element corresponds to the row of A. One could say this first coloumn of B is an index for choosing the row of A. Because C++ start counting by zero I substract one for my index. Here is my code:
std::vector< std::vector<int> > C(4, std::vector<int>(16));
std::vector<int> index(4);
std::vector<int> vectorA(4);
std::vector<int> vectorB(4);
for( int y = 0; y < 16; y++)
{
for(int i=0; i<4; ++i){
vectorA[i] = A[ B[y][0]-1 ][i];
}
for( int x = 1; x < 4; x++)
{
vectorB[x -1] = B[y][x];
}
C[ B[y][0] -1][index[ B[y][0] -1] ] = inner_product(vectorA.begin(), vectorA.end(), vectorB.begin(), 0);
index[B[y][0]-1] += 1;
}
This results in my matrix C:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 3 1 2 1 2 2 3 0 0 0 0 0 0 0
The first two rows are correct but row three and four are false.
The correct solution has to be (maybe except of ordering in row 3 and 4):
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
4 3 3 2 3 2 3 2 2 0 0 0 0 0 0 0
Where is my problem? Please help, it drives me crazy :( I tried showing each variable by step but can't find why is it false.
Thanks and greetings.
I have to agree with the other comments: Your code is kind of confusing. You should really simplify the access of vectors by index.
First simple thing you should do is to change the first column of B to be zero-based. All stuff in C++ is zero-based. Adopt it. Do not start adjusting it in your code by substracting one. (This does not gain much simplicity, but is is symptomatic for your code.)
Another source of confusion is that you use the first column of B as an index into A. This might be an implication from the problem you'd like to solve, but it makes things unclear: first column of B has a totally different meaning, always code in a way that objects are seperated by their meaning.
For me the most confusing thing is, that I really do not get what you're up to. With inner product you mean dot product, right? You have 2 sets of vectors you want to calculate the dot product of. This should result in a set of scalars, a 1D vector not a 2D matrix. You do some special stuff with this index vector, which makes the result being a 2D matrix. But you haven't explained the purpose/system behind it. Why do you need a vector for index, not just a scalar??
Vector index is the most ugly/complex part of your code. Without having a clue what you are up to, I would still guess that you find out what is going wrong when you start printing out the full vector index on every iteration and check if it is changing the way you expect.
I don't know what's the rationale behind OP choices, so I can't properly comment the design of code provided, but for what I can understand there are some mistakes with the example input too.
Given A and B matrices as presented, the inner product of the lower rows of A with the corresponding in B is always 0:
B[1] { 2, 1, 0, 0, 0 },
row "2" or A[1] is { 0, 1, 0, 1 } <- B[4] { 2, 0, 0, 1, 0 },
B[5] { 2, 1, 0, 1, 0 },
The same for the succesive row. Only if swapped, the expected output can be obtained and so I did in my code.
vectorA and vectorB and the corresponding copy loops aren't really neccessary and probably are the cause of the wrong output:
for( int x = 1; x < 4; x++)
{ // ^^^^^ this should be <= to reach the last element
vectorB[x -1] = B[y][x];
}
My code, with the updated input and the direct use of A and B is:
#include <iostream>
#include <vector>
#include <numeric>
using vec_t = std::vector<int>; // I assume a C++11 compliant compiler
using mat_t = std::vector<vec_t>;
using std::cout;
int main() {
mat_t A{
{ 0, 0, 0, 0 },
{ 1, 0, 1, 0 }, // <-- those lines are swapped
{ 0, 1, 0, 1 }, // <--
{ 1, 1, 1, 1 }
};
mat_t B{
{ 1, 0, 0, 0, 0 },
{ 2, 1, 0, 0, 0 },
{ 3, 0, 1, 0, 0 },
{ 4, 1, 1, 0, 0 },
{ 2, 0, 0, 1, 0 },
{ 2, 1, 0, 1, 0 },
{ 4, 0, 1, 1, 0 },
{ 4, 1, 1, 1, 0 },
{ 3, 0, 0, 0, 1 },
{ 4, 1, 0, 0, 1 },
{ 3, 0, 1, 0, 1 },
{ 4, 1, 1, 0, 1 },
{ 4, 0, 0, 1, 1 },
{ 4, 1, 0, 1, 1 },
{ 4, 0, 1, 1, 1 },
{ 4, 1, 1, 1, 1 }
};
mat_t C(4, vec_t(16));
vec_t pos(4);
for ( int i = 0; i < 16; ++i )
{
int row = B[i][0] - 1;
int col = pos[row];
int prod = std::inner_product( A[row].begin(), A[row].end(),
++(B[i].begin()), 0 );
// ^^^ skip the first element
C[row][col] = prod;
if ( prod )
++pos[row];
}
for ( auto & r : C )
{
for ( int x : r ) {
cout << ' ' << x;
}
cout << '\n';
}
return 0;
}
The output is:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
1 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0
2 2 3 2 3 2 3 3 4 0 0 0 0 0 0 0
I don't know if the ordering of the last row is as expected, but it mimics the logic of OP's code.
Related
Let's say my adjacency list is as follows:
0 : 1
1 : 0
it's reverse should be empty because there is two arcs in the initial list:
0:
1:
or
0 : 1
1 :
becomes
0 :
1 : 0
another example:
0 :
1 :
becomes
0 : 1
1 : 0
last example
0 : 1, 4
1 : 0, 4
2 : 0, 1, 3, 4
3 :
4 : 3, 1
becomes
0 : 2, 3
1 : 2, 3
2 :
3 : 0, 1, 2, 4
4 : 0, 2
is there an algorithm to do this ?
Graphe *Graphe::grapheInverse( void ){
Graphe *r = new Graphe (_adjacences.size() );
for (unsigned i = 0; i < _adjacences.size(); i++)
for ( unsigned j = 0; j < _adjacences[i]->size(); j++ )
if ( (*_adjacences[i])[j] == 1 ) // or 0 or 2 or 3 or 4 or ... like last example
//r->addArcs( i, (*_adjacences[i])[j] ); //adds an arc from A to B
return r;
}
Just invert the adjacency matrix.
Wherever you have a 0, replace it with a 1, and vice versa. Only exclude the diagonal, always put a 0 there.
im absolut new to cpp, I tried to code a simple 2D array matrix.
Here is what I'm talking about:
#include <iostream>
#include <string>
using namespace std;
void printTable()
{
int tabelle [10][10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int i, j;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
printf("%d ", tabelle[i][j]);
}
printf("\n");
}
}
int main(int argc, char* argv[])
{
printTable();
return 0;
}
This is how it looks like:
1 2 3 4 5 6 7 8 9 10
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 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
And this is how it should look like:
1 2 3 4 5 6 7 8 9 10
2 0 0 0 0 0 0 0 0 0
3 0 0 0 0 0 0 0 0 0
4 0 0 0 0 0 0 0 0 0
5 0 0 0 0 0 0 0 0 0
6 0 0 0 0 0 0 0 0 0
7 0 0 0 0 0 0 0 0 0
8 0 0 0 0 0 0 0 0 0
9 0 0 0 0 0 0 0 0 0
10 0 0 0 0 0 0 0 0 0
Thx for any advise :D
That's not how array assignments work in C++.
Think of 2D arrays as a 1D array of 1D arrays.
int tabelle[10][10] = {{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {3, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {4, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {6, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {7, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {8, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {9, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {10, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
your code is working correctly, 2d array is set of one dimension
array.
here 2d array tabelle[10][10]'s first one dimension array tablelle[0] is initialized with elements.
One more thing partially initialized array fills the rest of the element with
zero, that is why all other element are zero.
There are several different methods to initialize your 2D array, with the same result:
int tab[4][4] = {{1,2,3,4},{2},{3},{4}};
int bat[4][4] = {1,2,3,4,2,0,0,0,3,0,0,0,4,0,0,0};
The thing to keep in mind is that this kind of array is automatically allocated on the stack by the compiler and is stored as a linear sequential array in memory (see the second method above).
Also, for C++, the array you create in a function by automatic allocation in this manner has a scope limited to that function; after the function call ends, the array is gone. If you want to create an array in a function and pass it back to the main function for use, it has to be dynamically (heap) allocated; you then pass a pointer to that array back to main, and then you have to manage that memory by hand (assuming you didn't use a smart pointer to make it).
Note: You can also initiate your array as follows, for very large arrays:
myarray[100][100] = {}; //sets all elements to 0
for (int i = 0; i < 100; i++) {
myarray[0][i] = i + 1;
myarray[i][0] = i + 1;
}
Never do this:
myarray[100][100];
As this creates an array full of junk values loaded with whatever random bits happen to have been previously stored in that memory location, and you might forget to overwrite them later.
I went through different regex documents for this but I'm still not getting it. I hope someone will be able to help me.
I have a table like this:
program 1 0 1 1 0 0 0 0 0 0 0 1
stmt_list 2 0 2 2 0 0 0 0 0 0 0 3
stmt 4 0 5 6 0 0 0 0 0 0 0 0
I want to read it from file and store in an array. I did the following:
val source = io.Source.fromFile("file.txt").getLines.toList.mkString.split("\\W+")
And I'm getting output like:
program
1
0
1
1
0
0
0
0
0
0
0
1stmt_list // this is problem, int and string together which I don't want.
2
0
2
2
0
0
0
0
0
0
0
3stmt
4
0
.
.
.
I learned \s matches any space, tab or newline character. But when I tried, I'm getting error on scala error: invalid escape character . I tried bunch of other steps: " +", /\W+/ etc. None is working. I would highly appreciate any help. My goal is to read the file into a 2D array with only string and int values.
Your problem isn't so much the Regex itself, but the fact that you "merge" all the lines into one String (using mkString) instead of operating on each line separately, using map:
val source = Source.fromFile("file.txt")
.getLines.toList // gets a list of file lines
.map(_.split("\\W+").toList) // maps each line into a list
source.foreach(println)
// List(program, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1)
// List(stmt_list, 2, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0, 3)
// List(stmt, 4, 0, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0)
I have k (0 < k < 8) CSV files containing values all 0 or 1.
My C++ code reads from the file and stores the content of each file into a vector<signed char>.
I wished to merge (concat) then store them in a single vector<signed char>.
File 1: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Stored in vector1
File 2: 1 1 1 0 0 0 0 0 0 1 1 0 0 0 1 0 0 0 0 0 Stored in vector2
File 3: 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Stored in vector3
File 4: 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Stored in vector4
File 5: 1 1 0 1 1 0 0 0 1 1 1 0 0 0 1 0 0 0 1 0 Stored in vector5
I wished to store them in vector<signed char> vectork:
with vectork[0] stored where each element has bit pattern as [0 0 0 0 1 0 1 1] -- first col
with vectork[1] stored where each element has bit pattern as [0 0 0 0 1 1 0 1] -- second col
with vectork[2] stored where each element has bit pattern as [0 0 0 0 1 0 0 0] -- third col
I tried with
vectork.resize(vector1.size(),0);
for ( int i = 0; i < vector1.size(); i++ ) {
vectork[i] = vectork[i] << 1;
if (vector1[i] == 1) vectork[i] +=1;
vectork[i] << 1;
if (vector2[i] == 1) vectork[i] +=1;
vectork[i] << 1;
if (vector3[i] == 1) vectork[i] +=1;
vectork[i] << 1;
if (vector5[i] == 1) vectork[i] +=1;
}
Is the above correct?
This would be a lot easier done with bitsets, however, if you choose to do it this way, it would look something like this.
I'm still kind of confused as to what exactly you're trying to do, but it seems like you're trying to get all of those vectors into one two dimensional vector (you did as an array of vectors, but I feel as if you intended it like this).
This will get all the vectors, and append them into a new vector of vectors.
// Example program
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
vector<signed char> vector1 = {0,1,0,1,0,1,0,1};
vector<signed char> vector2= {0,0,0,1,0,1,0,1};
vector<signed char> vector3= {0,1,1,1,0,1,0,1};
vector<signed char> vector4= {1,1,0,1,0,1,0,1};
vector<signed char> vector5= {1,0,0,1,0,1,0,1};
vector<vector<signed char>> vectork(5, vector<signed char>(8));
vectork.clear();
vectork.push_back(vector1);
vectork.push_back(vector2);
vectork.push_back(vector3);
vectork.push_back(vector4);
vectork.push_back(vector5);
//to check if it correctly works (it does).
for(vector<signed char> v : vectork) {
for(signed char i : v) {
printf("%d ", i);
}
printf("\n");
}
}
The output would look like this:
0 1 0 1 0 1 0 1
0 0 0 1 0 1 0 1
0 1 1 1 0 1 0 1
1 1 0 1 0 1 0 1
1 0 0 1 0 1 0 1
Let me know if you were trying to do something slightly different and I can tweak it for you, or if you need any explanation on what I wrote, or have any questions in general.
Firstly I would recomend that you use std::vector<bool> instead of std::vector<signed char> This is specifically for performance reasons as your compiler will likely reduce the memory usage by storing 8 Booleans in 1 byte as apposed to storing 1 Boolean in a byte. Secondly I think you have completely misunderstood the process of bit shifting, as far as I am aware from what you have posted you are simply trying to concatenate two STL Vectors this has been asked here. For reference I have included a code snippet from the excellent answer by Robert Gamble. In your
vector1.insert( vector1.end(), vector2.begin(), vector2.end() );
#include <vector>
std::vector<signed char>
merge(const std::vector<signed char>& vector1,
const std::vector<signed char>& vector2,
const std::vector<signed char>& vector3,
const std::vector<signed char>& vector4,
const std::vector<signed char>& vector5)
{
std::vector<signed char> result;
result.reserve(vector1.size());
auto i1 = vector1.begin();
auto i2 = vector2.begin();
auto i3 = vector3.begin();
auto i4 = vector4.begin();
auto i5 = vector5.begin();
while (i1 != vector1.end()) {
int n = 0;
for (auto *v: { &i1, &i2, &i3, &i4, &i5 })
n = n*2 + *(*v)++;
result.push_back(n);
}
return result;
}
// test it:
#include <algorithm>
int main()
{
auto v = merge({ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0 },
{ 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0 });
auto expected = { 0b1011, 0b1101, 0b1000, 0b0001, 0b0001, 0b0000, 0b0000, 0b0000,
0b0001, 0b1001, 0b1001, 0b0000, 0b0000, 0b0000, 0b1001, 0b0000,
0b0000, 0b0000, 0b1001, 0b0000 };
return !std::equal(expected.begin(), expected.end(), v.begin());
}
I have a problem that from a certain number 1 in a 2D matrix with (x, y) coordinates. From this number, it will start spreading out its 4-neighbor which their values will be assigned by (start point + 1)
We start from a coordinate of (3, 3) = 1. Its neighbor's value will be 2. Next step, 4 neighbors of the point having value of 2 will be 3. And so on, until, all 1 numbers in the matrix are infected!
I have resolved this problem by using some loops. However, I'd like to resolve it by another way that is recursion. But I haven't done with it.
Before
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 1 1 1 1 1 1 0 0
0 0 1 1 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0 0 0
0 0 1 1 1 0 0 0 0 0
0 0 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
After spreading out
0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
0 0 3 2 3 0 0 0 0 0
0 0 2 1 2 3 4 5 0 0
0 0 3 2 3 4 0 0 0 0
0 0 0 0 4 5 0 0 0 0
0 0 0 0 5 6 0 0 0 0
0 0 8 7 6 0 0 0 0 0
0 0 9 8 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0
Below is my code but I just can spread all 1 numbers with another value but not as I want. So please help me resolve this problem.
#include <iostream>
#define MAX 10
using namespace std;
int data[MAX][MAX] = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 1, 1, 1, 0, 0},
{0, 0, 1, 1, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 0, 0, 1, 1, 0, 0, 0, 0},
{0, 0, 1, 1, 1, 0, 0, 0, 0, 0},
{0, 0, 1, 1, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
int mark[MAX][MAX];
void spreading(int x, int y, int v){
if (x < 0 || x == MAX) return;
if (y < 0 || y == MAX) return;
if(data[x][y] == 0 || mark[x][y] != 0)
return;
data[x][y] = v;
mark[x][y] = v;
spreading(x + 1, y, v);
spreading(x, y + 1, v);
spreading(x - 1, y, v);
spreading(x, y - 1, v);
}
void printArr(int a[MAX][MAX]){
for (int i = 0; i < MAX; ++i) {
cout << endl;
for (int j = 0; j < MAX; ++j) {
cout << a[i][j] << " ";
}
}
}
int main(){
spreading(3, 3, 1);
printArr(data);
system("pause");
return 0;
}
Following may solve your issue: (https://ideone.com/VQmBhU)
void spreading(int x, int y, int v){
// Test if x, y is inside the propagation area
if (x < 0 || x == MAX) return;
if (y < 0 || y == MAX) return;
if (data[x][y] == 0) return;
// if already visited with a better path, cancel.
// if not visited, or the previous visit was worst than this try, continue
if (mark[x][y] != 0 && mark[x][y] <= v) return;
data[x][y] = v;
mark[x][y] = v;
spreading(x + 1, y, v + 1);
spreading(x, y + 1, v + 1);
spreading(x - 1, y, v + 1);
spreading(x, y - 1, v + 1);
}
Some example of 're' visit (with the mark array content):
(1) 0 -> 1 (2) -> 1 2 -> 1 2
0 0 0 0 0 (3) (4) 3
1 <= 5, 3 <= 5 : (4) finished
2 <= 4 : (3) finished
1 <= 3 : (2) finished
4 > 2 : we continue propagation from (1)
(1) 2 -> 1 2
4 3 (2) 3
...