I wrote a method that multiplies matrices. It works fine, but gives additional column of zeros. The result of multiplying is correct. Here is the code of method:
Matrix Matrix::multiplyMatrix(Matrix second)
{
vector<vector<double> > sum(vec.size(), vector<double> (vec[0].size()));
if (vec[0].size()!=second.vec.size())
{
throw "Dimensions are not correct";
}
else
{
for (int i=0; i<vec.size(); i++)
{
for (int j=0; j<second.vec[0].size(); j++)
{
sum[i][j]=0;
for (int k=0; k<vec[0].size(); k++)
{
sum[i][j]+=vec[i][k]*second.vec[k][j];
}
}
}
Matrix out(vec.size(), vec[0].size());
out.vec=sum;
return out;
}
}
From main:
Matrix A("A.txt",3,4);
Matrix B("B.txt",4,3);
auto C=A.multiplyMatrix(B);
C.write("C.txt");
Matrices:
A:
2 3 4 4
1 2 4 6
1 1 0 1
and
B:
1 2 3
5 6 7
9 1 5
4 5 5
Instead of 3x3 matrix it gives:
69 46 67 0
71 48 67 0
10 13 15 0
Do you know what is the problem?
Thanks
Your matrix named "out" has the wrong dimensions, also, int the first line of your code, the sum has wrong dimensions too.
the first line should change to:
vector<vector<double> > sum(vec.size(), vector<double> (second.vec[0].size()));
the definition of out should change to:
Matrix out(vec.size(), second.vec[0].size());
Related
I am facing problem with a 2D matrix consist of 3 column and N rows. Now I wanted to sort the matrix in such a way that the smallest of the first row is the first element, and so on. The first element of the second row is the smallest number with the smallest value of the first row. and similar to 3rd row. For example,
A B C
5 2 6
6 5 8
2 9 4
4 5 8
2 3 5
2 9 2
so the sorted matrix will be
A B C
2 3 5
2 9 2
2 9 4
4 5 8
5 2 6
6 5 8
Also, it will store the index of them such that
A_i B_i C_i
5 5 5
6 6 6
3 3 3
and so on...
I implemented this using C++ which is not computationally efficient and takes so much time for a very big matrix. How I can Implement this a computationally efficient way and fast?
My current C++ code for the same is as follow
for(int tii=0; tii<f_sizee; tii++){
track_index(tii)=tii+1;
}
for(int chkhk=0;chkhk<f_sizee;chkhk++){
if(check_index(chkhk)==1){
for(int chkhk1=chkhk+1;chkhk1<f_sizee;chkhk1++){
if((Va_mat(chkhk,0)==Va_mat(chkhk1,0))&&(Va_mat(chkhk,1)==Va_mat(chkhk1,1))&&(Va_mat(chkhk,2)==Va_mat(chkhk1,2))){
check_index(chkhk1)=0;
track_index(chkhk1)=seed_ind;
}
else track_index(chkhk)=seed_ind;
}
seed_ind=seed_ind+1;
}
}
int new_dim=sum(check_index);
int new_count=0;
mat unsort_vmat=zeros(new_dim,Va_mat.n_cols);
for(int iij=0; iij<f_sizee; iij++){
if(check_index(iij)==1){
unsort_vmat.row(new_count)=Va_mat.row(iij);
new_count++;
}
}
mat sort_vmat=zeros(new_dim,Va_mat.n_cols);
uvec indices = stable_sort_index(unsort_vmat.col(0));
int contrrS=0;
for(int sort_f=0; sort_f < new_dim; sort_f++){
for(uword sort_f2=0; sort_f2 < Va_mat.n_cols; sort_f2++){
contrrS=indices(sort_f);
sort_vmat(sort_f,sort_f2)=unsort_vmat(contrrS,sort_f2);
}
}
mat sort_vmat2 = zeros(new_dim,Va_mat.n_cols);
sort_vmat2 = sort_vmat ;
double element_tmp=0;
for(int iitr=0; iitr < new_dim; iitr++){
for(int iitk=iitr; iitk < new_dim; iitk++){
if(sort_vmat(iitk,0)==sort_vmat(iitr,0)){
if(sort_vmat(iitk,1)>sort_vmat(iitr,1)){///if error, delete this brace
element_tmp=sort_vmat(iitr,1);
sort_vmat(iitr,1)=sort_vmat(iitk,1);
sort_vmat(iitk,1)=element_tmp;
}
}
}
}
vec new_ind=zeros(f_sizee);
int start_ind=0;
for(int new_index=0; new_index<f_sizee; new_index++){
new_ind(new_index)=start_ind;
start_ind++;
}
int itr_count=0;
for(uword itr1=0; itr1<Va_mat.n_rows; itr1++){
for(int itr2=0; itr2<new_dim; itr2++){
if((Va_mat(itr1,0)==sort_vmat2(itr2,0))&&(Va_mat(itr1,1)==sort_vmat2(itr2,1))&&(Va_mat(itr1,2)==sort_vmat2(itr2,2))){
new_ind(itr_count)=itr2+1;
itr_count++;
}
}
}
int funda=0;
for(unsigned int Faa=0; Faa<Fa_mat.n_rows; Faa++){
for(unsigned int Fab=0; Fab<Fa_mat.n_cols; Fab++){
Fa_mat(Faa, Fab)=new_ind(funda);
funda++;
}
}
I want to rotate just the outer ring of a matrix clockwise.
Where n=number of steps to be rotate clockwise.
Suppose if I have a 4x5 matrix.
1 2 3 4 5
6 7 8 9 0
5 4 2 5 7
8 2 7 9 3
Now if n=1 the output should be :-
6 1 2 3 4
5 7 8 9 5
8 4 2 5 0
2 7 9 3 7
I have tried the logic of :
int temp = im[i][j];
im[i][j] = im[n-1-j][i];
im[n-1-j][i] = im[n-1-i][n-1-j];
im[n-1-i][n-1-j] = im[j][n-1-i];
im[j][n-1-i] = temp;
But I know this logic is completely wrong as it is moving the whole matrix.
You can do it like this:
Map and copy the border to a flat array
Apply std::rotate
Copy rotated array back into the border
Here is a sample implementation:
void rotate_border(int m[R][C], int n) {
vector<int> tmp(2*(R+C-2), -1);
for (size_t c = 0 ; c != C ; c++) {
tmp[c] = m[0][c];
tmp[c+C+R-2] = m[R-1][C-c-1];
}
for (size_t r = 1 ; r != R-1 ; r++) {
tmp[C+r-1] = m[r][C-1];
tmp[2*C+R-3+r] = m[R-r-1][0];
}
std::rotate(tmp.begin(), std::next(tmp.begin(), n), tmp.end());
for (size_t c = 0 ; c != C ; c++) {
m[0][c] = tmp[c];
m[R-1][C-c-1] = tmp[c+C+R-2];
}
for (size_t r = 1 ; r != R-1 ; r++) {
m[r][C-1] = tmp[C+r-1];
m[R-r-1][0] = tmp[2*C+R-3+r];
}
}
Demo.
Positive numbers rotate border counterclockwise. For clockwise rotation subtract the number from the size of the border. For example, 4✕5 matrix has the border of size 14, i.e. 5+(4-2)+5+(4-2). Hence, rotating by 1 clockwise requires rotating by 14-1.
I'm having trouble figuring out the thought process behind grabbing adjacent vertical elements in a grid. Say I have a 5x5 grid:
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
20 21 22 23 24
I want to find all adjacent horizontal and vertical adjacent elements and place them into an array. The size of the array is given by the possible number of walls between each element (not counting the outside) e.g.
1 | 2 | 3
--- --- ---
4 | 5 | 6
A graph of 2x3 has 7 walls so the array would look like
1 2
2 3
4 5
5 6 //end of horizontal walls
1 4 //beginning of vertical walls
2 5
3 6
now I've figured out how to find all horizontal walls given rows and cols, where walls is the array I will be storing the result in:
//find all horizontal walls in grid
//2-d array to store the element between the wall (0 1) (1 2)
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols-1; c++){
int s = r > 0 ? -1*r : 0; //after first row always write over last space
walls[r*rows+c+s][0] = r*rows+c;
walls[r*rows+c+s][1] = r*rows+c+1;
}
}
but I'm just getting lost on figuring out how to determine all vertical walls, in a grid of 5x5 for example the vertical walls would be
0 5
5 10
10 15
15 20
1 6
6 11
etc...
here's what I'm currently trying:
for(int r = 0; r < rows; r++){
for(int c = 0; c < cols; c++){
//just print the values at the moment, setting walls properly is easy
std::cout << r*rows+c*cols << " " << r*rows+c*cols+5 << std::endl;
}
}
only problem is this does not reset after the first column to 1, instead it continues on like:
0 5
5 10
10 15
15 20
20 25 //nope, should be 1 6
and suggestions? pseudo-code is much appreciated I would prefer an explanation over code
Ok, just figured out the solution so I'll post all I did:
the problem I had was rows did not recent back to 1 when the inner for loop left and started again, this was because I was still multiplying r by rows, this was actually a really simple fix:
r*rows+c*cols << " " << r*rows+c*cols+5 <<
becomes
r+c*cols << " " << r+c*cols+5 <<
I also was running the inner for loop one too many times so, changing
c < cols should become c < cols-1 and now my output is:
0 5
5 10
10 15
15 20
1 6
6 11
11 17
etc...
I am successful in displaying Diagonal Array elements, but failed to display Non Diagonal array elements I tried a lot but unsuccessful. Here is the code what I am try with I am using Turbo C++ -
#include<conio.h>
#include<iostream.h>
void accept(int a[4][4],int size)
{
cout<<"Diagonal One:";
for (int i=0;i<size;i++)
for(int j=0;j<size;j++)
if (i!=j)
cout<<"\n"<<i <<" "<<j<<" "<<a[i][j];
}
void main()
{
int a[4][4]={{5,4,3,4},{6,7,9,1},{8,0,3,7},{2,4,5,9}};
clrscr();
accept(a,4);
getch();
}
Example : if the array content is
5 4 3 4
6 7 9 1
8 0 3 7
2 4 5 9
Output through the function should be :
4 3 6 1 8 7 4 5
Output is displaying some of the diagonal elements also.
The function skips all elements in the diagonal 5739 (i != j takes care of this), but, based on the desired output, you also wish to skip all elements in the diagonal 4902.
To also check for the other diagonal, replace
if (i != j)
with
if (i != j && i != size-j-1)
Test.
When the following program is fead the following input (reading from cin):
1 1 1 1 2 1 1 1 1 1 1 1 1 1 1 1
The output is surprising:
1 1 1 2 2 1 1 1 1 1 1 1 1 1 1 1
#include<iostream>
using namespace std;
int main()
{
int arey[3][3];
int i,j;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cin>>arey[j][i];
}
}
arey[0][0]=1;
arey[3][3]=1;
i=0,j=0;
for(j=0;j<=3;j++)
{
for(i=0;i<=3;i++)
{
cout<<arey[j][i];
}
}
return 0;
}
Can someone explain what I should change to get the same output as the input?
Is the matrix 3x3 or 4x4?
you created 3x3 but the loops run for 4 elements and you also update [3][3]
Basically your indexes overflow and you overwrite a different cell in the matrix.
Update: cheecked your input, use: int arey[4][4];
Arrays use 0 based indices, so the valid range of indices for your
int arey[3][3];
are 0 <= i < 3 and 0 <= j < 3
So you need to change the condition in your for loops to be strictly < instead of <=
I really don't think I understand your question, but this is wrong:
int arey[3][3];
...
for(j=0;j<=3;j++) // <= invalid
...
array[3][3]=1; // out of bounds
arey is a 3*3 array. You can't access arey[3][?], that's out of bounds. The only valid indices are 0..2.
Once you've written past the bounds of your array, your program behavior becomes undefined.