Probably a simple fix, but I keep getting 0 as the determinate when I should be getting 22, I have to use dynamic memory allocation as well. Might be some problem with using floats as I am not completely familiar with how they work with pointers. Honestly don't know what could be causing the function to output a zero.
cpp.sh link to test: http://cpp.sh/5bu2v
#include <iostream>
#include <math.h>
using namespace std;
float determinant(float *mat1, int &rows1)
{
float s = 1, D = 0;
float *temp = new float[rows1 * rows1];
int i, j, m, n, c;
if (rows1 == 1)
{
return (*(mat1 + 0 * rows1 + 0));
}
else
{
D = 0;
for (c = 0; c < rows1; c++)
{
m = 0;
n = 0;
for (i = 0; i < rows1; i++)
{
for (j = 0; j < rows1; j++)
{
*(temp + i * rows1 + j) = 0;
if (i != 0 && j != c)
{
*(temp + m * rows1 + n) = *(mat1 + i * rows1 + j);
if (n < (rows1 - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
int V1 = rows1 - 1;
D = D + s * (*(mat1 + 0 * rows1 + c) * determinant(temp, V1));
s = -1 * s;
}
}
return (D);
}
int main()
{
int i, j;
int n = 3;
int matrix[10][10] = {{1, 2, 3},
{0, 4, 5},
{1, 0, 6}};
float *mat1 = new float[n * n];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
*(mat1 + i * n + j) = matrix[i][j];
}
}
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
cout << matrix[i][j] << " ";
cout << endl;
}
cout << "Determinant of the matrix is " << determinant(mat1, n);
return 0;
}
Your first call into determinant, mat is a 3x3 matrix stored in a 1 dimensional array. Visualize it like this:
A B C
D E F
G H I
You create another 3x3 matrix, temp.
You series of loops to fill the temp matrix exclude the first row and column c, so it ends up looking like this the first time thru:
D E 0
G H 0
0 0 0
This gets passed to determinant, which is expecting a 2x2 matrix. Since you've passed it something else, what the recursive call sees is
D E
0 G
When you construct temp you need to do it with the smaller matrix size, not the source size.
Related
I'm doing a homework assignment which involves multiplying more than 2 matrices.
I thought about multiplying the first 2 matrices then take its result, continue multiplying it with the 3rd matrix, and repeat the same process until I multiply all the matrices together.
A * B * C = (A * B) * C = A * (B * C)
And here is my code so far. All of my matrices are stored in a 3D array of matrix[1][row][column].
// Calculate the result of first 2 matrices
for (int a = 0; a < n7; a++) {
for (int b = 0; b < n7; b++) {
for (int l = 0; l < n7; l++) {
sum += matrix[1][l][b] * matrix[0][a][l];
}
resultMatrix[a][b] = sum;
sum = 0;
}
}
// Check if k > 2, if yes then continue taking matrix[2] multiply with the result
if (k > 2) {
// Calculate to a tempResult matrix
for (int f = 2; f < k; f++) {
for (int a = 0; a < n7; a++) {
for (int b = 0; b < n7; b++) {
for (int l = 0; l < n7; l++) {
sum += matrix[f][l][b] * resultMatrix[a][l];
}
resultMatrix[a][b] = sum;
sum = 0;
}
}
// Pass the result to the original resultMatrix
for (int a = 0; a < n7; a++) {
for (int b = 0; b < n7; b++) {
resultMatrix[a][b] = tempResult[a][b];
}
}
}
}
I could not get the same result with an online matrix calculator and some manual input.
Please point out my mistakes, thank you!
Here is one solution.. Although I didn't applied dimension check of the matrices. So if you multiply a (3X4) & (2X4) matrix, it will not warn you. It can be done very easily with very simple steps. It worked for me with
A = 1 2 3 4
5 6 7 8 [4X4]
0 1 2 3
7 8 9 0
B = 2 3 4
5 6 7 [4X3]
8 9 0
3 4 5
c = 1
2 [3X1]
3
D = 1 1 -2 -1 [1X4]
Result = 278 278 556 -278
718 718 1436 -718 [4X4]
168 168 336 -168
678 678 1356 -678
The program:
#include <iostream>
#include <iomanip>
void displaymat(double* p, int r, int c)
{
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
std::cout << std::setw(15) << *(p + i * c + j) << "\t";
}
std::cout << std::endl;
}
std::cout << "\n\n" << std::endl;
}
void matrix_multiply(double** a, double* b, int* rf, int* cf, int num)
{
double sum;
double** interim_result = new double* [num - 1]{nullptr};
for (int i = 0; i < num - 1; i++)
{
interim_result[i] = new double[rf[0] * cf[i + 1]]{ 0 };
}
for (int i = 0; i < num - 1; i++)
{
for (int j = 0; j < rf[0]; j++)
{
for (int k = 0; k < cf[i + 1]; k++)
{
sum = 0;
for (int l = 0; l < cf[i]; l++)
{
if (i == 0)
{
sum = sum + a[i][cf[i] * j + l] * a[i + 1][cf[i + 1] * l + k];
}
else
{
sum = sum + interim_result[i - 1][cf[i] * j + l] * a[i + 1][cf[i + 1] * l + k];
}
}
interim_result[i][j * cf[i + 1] + k] = sum;
}
}
//displaymat(interim_result[i], rf[0], cf[i + 1]);
}
for (int i = 0; i < rf[0] * cf[num - 1]; i++)
{
b[i] = interim_result[num - 2][i];
}
for (int i = 0; i < num - 1; i++)
{
delete[] interim_result[i];
}
delete[] interim_result;
}
int main()
{
int num; // total number of matrices
char ch = 'a';
std::cout << "How many matrices/matrix?:";
std::cin >> num;
std::cout << std::endl;
double** mat = new double* [num]; // double pointer for stacks of matrices
int* r = new int[num]{0}; // to store the rows the matrices
int* c = new int[num]{0}; // to store the columns of matrices
for (int n = 0; n < num; n++)
{
std::cout << "matrix:" << n + 1 << "\n" << std::endl;
std::cout << "rows:";
std::cin >> r[n]; // input
std::cout << "columns:";
std::cin >> c[n]; // input
std::cout << std::endl;
mat[n] = new double[(r[n] * c[n])]; // for getting elements
for (int i = 0; i < c[n] * r[n]; i++)
{
std::cout << ch << "[" << i / c[n] + 1 << "][" << i % c[n] + 1 << "]:";//ch << "[" << i / c[n] << "]" << "[" << i % c[n] << "]:";
std::cin >> *(*(mat + n) + i);
}
displaymat(mat[n], r[n], c[n]);
ch++;
}
double* result = new double[r[0] * c[num - 1]];
matrix_multiply(mat, result, r, c, num);
std::cout << "Result=" << std::endl;
displaymat(result, r[0], c[num - 1]);
for (int i = 0; i < num; i++)
{
delete[] * (mat + i);
}
delete[] mat;
delete[] result;
delete[] r;
delete[] c;
}
#include <bits/stdc++.h>
using namespace std;
//Program to find the nth fib number using matrix exponentation
void multi_mat(int A[3][3], int B[3][3])
{
int res_mat[3][3];
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
res_mat[i][j] = 0;
for (int k = 0; k < 3; k++)
{
res_mat[i][j] += A[i][k] * B[k][j];
}
}
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
A[i][j] = res_mat[i][j];
}
}
}
int power(int F[3][3], int n)
{
int M[3][3] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
if (n == 1)
return F[0][0] + F[0][1];
power(F, n / 2);
multi_mat(F, F);
if (n % 2 != 0)
multi_mat(F, M);
return F[0][0] + F[0][1];
}
int findfib(int n)
{
int F[3][3] = {{1, 1, 1}, {1, 0, 0}, {0, 1, 0}};
if (n == 0)
return 0;
if (n == 1 || n == 2)
return 1;
return power(F, n - 2);
}
int main()
{
int n = 0;
cin >> n;
cout << "The fib of the " << n << "th number is : " << findfib(n) << '\n';
return 0;
}
This is the code for matrix exponentiation. I'm having trouble understanding where does the data get stored when the multi_mat function is invoked. Also when I call the multi_mat function does the matrix res_mat hold the values when it was previously invoked or does it initialize it with some junk value?
where does the data get stored when the multi_mat function is invoked
Initially, it's stored in res_mat:
res_mat[i][j] += A[i][k] * B[k][j];
but some lines later, it's copied to A:
A[i][j] = res_mat[i][j];
So at the end of the execution, the place where the result is stored is the first argument A, which outside the function is called F, as the function was invoked like:
multi_mat(F, F);
does the matrix res_mat hold the values when it was previously invoked or does it initialize it with some junk value?
Yes, it has "junk" values at this point:
int res_mat[3][3];
but, it's later initialized to zeroes when this line executes for each element of the matrix:
res_mat[i][j] = 0;
So, I have the following problem:
From the file tabl.in a number n will be read (n<=50).
After that a square array with n rows and n columns will be read; all the numbers in the array will be composed by a maximum of 2 digits each.
Shown in the file tabl.out, the modulo between the sum of numbers found on the second diagonal of the array and 10, if the sum is palindrome (true=1, false=0), and the arithmetic mean of elements situated below of the main diagonal.
Will be writing functions for:
reading the array
calculation of the operation sum of secondary diagonal%10
checking if the previous result it is palindrome
calculation of the arithmetic mean below main diagonal
Example:
tabl.in:
4
5 8 2 12
1 0 3 16
1 2 1 11
5 7 2 19
tabl.out:
2 1 3
where
(12+3+2+5)%10 = 22%10 = 2
22 is palindrome = 1
1+2+2+1+7+5 = 18, 18/6=3
My code so far is:
#include <fstream>
using namespace std;
ifstream fin("tabl.in");
ofstream fout("tabl.out");
void readn(int Arr[][51], int n) {
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
fin >> Arr[i][j];
}
int sumsec(int Arr[][51], int n) {
int s = 0;
float r;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
r = s % 10;
return r;
}
void pald(int Arr[][51], int n) {
int s = 0, pal = 0;
for (int i = 1; i < n; i++)
s = s + Arr[i][n - i + 1];
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == s)
fout << "1 ";
else
fout << "0 ";
}
int ambmd(int Arr[][51], int n) {
int s = 0, k;
float ame;
for (int i = 2; i <= n; i++) {
for (int j = 1; j <= i - 1; j++) {
s = s + Arr[i][j];
k++;
}
}
ame = s / k;
return ame;
}
int main() {
int Arr[51][51], n;
float r, ame;
fin >> n;
readn(Arr, n);
r = sumsec(Arr, n);
fout << r << " ";
pald(Arr, n);
ame = ambmd(Arr, n);
fout << ame;
}
But I have an issue with the palindrome() function: my output file will have 2 0 3 written to it for the given array from the example, instead of 2 1 3. What am I doing wrong?
Your pald function would work, if you compute s the same way as you do in sumsec and if s would still contain the sum, after you compute pal.
In your case, while (s != 0) {...}, followed by if (pal == s) {...} could be re-written as if (pal == 0), which is clearly not the intended solution. Just save your sum before computing pal, then compare with the saved sum.
Also, change your loop condition for computing s to for (int i = 1; i <= n; i++).
int s = 0, pal = 0, sum = 0;
for (int i = 1; i <= n; i++)
s = s + Arr[i][n - i + 1];
sum = s;
while (s != 0) {
pal = pal * 10 + s % 10;
s = s / 10;
}
if (pal == sum)
fout << "1 ";
else
fout << "0 ";
You should also consider the various comments for code improvements, like not re-computing the sum in the pald function.
I am trying to achieve the fftshift function (from MATLAB) in c++ with for loop and it's really time-consuming. here is my code:
const int a = 3;
const int b = 4;
const int c = 5;
int i, j, k;
int aa = a / 2;
int bb = b / 2;
int cc = c / 2;
double ***te, ***tempa;
te = new double **[a];
tempa = new double **[a];
for (i = 0; i < a; i++)
{
te[i] = new double *[b];
tempa[i] = new double *[b];
for (j = 0; j < b; j++)
{
te[i][j] = new double [c];
tempa[i][j] = new double [c];
for (k = 0; k < c; k++)
{
te[i][j][k] = i + j+k;
}
}
}
/*for the row*/
if (c % 2 == 1)
{
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < cc; k++)
{
tempa[i][j][k] = te[i][j][k + cc + 1];
tempa[i][j][k + cc] = te[i][j][k];
tempa[i][j][c - 1] = te[i][j][cc];
}
}
}
}
else
{
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < cc; k++)
{
tempa[i][j][k] = te[i][j][k + cc];
tempa[i][j][k + cc] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
te[i][j][k] = tempa[i][j][k];
}
}
}
/*for the column*/
if (b % 2 == 1)
{
for (i = 0; i < a; i++)
{
for (j = 0; j < bb; j++)
{
for (k = 0; k < c; k++)
{
tempa[i][j][k] = te[i][j + bb + 1][k];
tempa[i][j + bb][k] = te[i][j][k];
tempa[i][b - 1][k] = te[i][bb][k];
}
}
}
}
else
{
for (i = 0; i < a; i++)
{
for (j = 0; j < bb; j++)
{
for (k = 0; k < c; k++)
{
tempa[i][j][k] = te[i][j + bb][k];
tempa[i][j + bb][k] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
te[i][j][k] = tempa[i][j][k];
}
}
}
/*for the third dimension*/
if (a % 2 == 1)
{
for ( i = 0; i < aa; i++)
{
for (j = 0; j < b; j++)
{
for ( k = 0; k < c; k++)
{
tempa[i][j][k] = te[i + aa + 1][j][k];
tempa[i + aa][j][k] = te[i][j][k];
tempa[a - 1][j][k] = te[aa][j][k];
}
}
}
}
else
{
for (i = 0; i < aa; i++)
{
for ( j = 0; j < b; j++)
{
for ( k = 0; k < c; k++)
{
tempa[i][j][k] = te[i + aa][j][k];
tempa[i + aa][j][k] = te[i][j][k];
}
}
}
}
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
cout << te[i][j][k] << ' ';
}
cout << endl;
}
cout << "\n";
}
cout << "and then" << endl;
for (i = 0; i < a; i++)
{
for (j = 0; j < b; j++)
{
for (k = 0; k < c; k++)
{
cout << tempa[i][j][k] << ' ';
}
cout << endl;
}
cout << "\n";
}
now I want to rewrite it with memmove to improve the running efficiency.
For the 3rd dimension, I use:
memmove(tempa, te + aa, sizeof(double)*(a - aa));
memmove(tempa + aa+1, te, sizeof(double)* aa);
this code can works well with 1d and 2d array, but doesn't work for the 3d array. Also, I do not know how to move the column and row elements with memmove. Anyone can help me with all of these? thanks so much!!
Now I have modified the code as below:
double ***te, ***tempa1,***tempa2, ***tempa3;
te = new double **[a];
tempa1 = new double **[a];
tempa2 = new double **[a];
tempa3 = new double **[a];
for (i = 0; i < a; i++)
{
te[i] = new double *[b];
tempa1[i] = new double *[b];
tempa2[i] = new double *[b];
tempa3[i] = new double *[b];
for (j = 0; j < b; j++)
{
te[i][j] = new double [c];
tempa1[i][j] = new double [c];
tempa2[i][j] = new double [c];
tempa3[i][j] = new double [c];
for (k = 0; k < c; k++)
{
te[i][j][k] = i + j+k;
}
}
}
/*for the third dimension*/
memmove(tempa1, te + (a-aa), sizeof(double**)*aa);
memmove(tempa1 + aa, te, sizeof(double**)* (a-aa));
//memmove(te, tempa, sizeof(double)*a);
/*for the row*/
for (i = 0; i < a; i++)
{
memmove(tempa2[i], tempa1[i] + (b - bb), sizeof(double*)*bb);
memmove(tempa2[i] + bb, tempa1[i], sizeof(double*)*(b - bb));
}
/*for the column*/
for (j = 0; i < a; i++)
{
for (k = 0; j < b; j++)
{
memmove(tempa3[i][j], tempa2[i][j] + (c - cc), sizeof(double)*cc);
memmove(tempa3[i][j] + cc, tempa2[i][j], sizeof(double)*(c-cc));
}
}
but the problem is that I define too much new dynamic arrays and also the results for tempa3 are incorrect. could anyone give some suggestions?
I believe you want something like that:
memmove(tempa, te + (a - aa), sizeof(double**) * aa);
memmove(tempa + aa, te, sizeof(double**) * (a - aa));
or
memmove(tempa, te + aa, sizeof(double**) * (a - aa));
memmove(tempa + (a - aa), te, sizeof(double**) * aa);
depending on whether you want to swap the first half "rounded up or down" (I assume you want it rounded up, it's the first version then).
I don't really like your code's design though:
First and foremost, avoid dynamic allocation and use std::vector or std::array when possible.
You could argue it would prevent you from safely using memmove instead of swap for the first dimensions (well, it should work, but I'm not 100% sure it isn't implementation defined) but I don't think that would improve that much the efficiency.
Besides, if you want to have a N-dimensional array, I usually prefer avoiding "chaining pointers" (although with your algorithm, you can actually use this structure, so it's not that bad).
For instance, if you're adamant about dynamically allocating your array with new, you might use something like that instead to reduce memory usage (the difference might be neglectible though; it's also probably slightly faster but again, probably neglectible):
#include <cstddef>
#include <iostream>
typedef std::size_t index_t;
constexpr index_t width = 3;
constexpr index_t height = 4;
constexpr index_t depth = 5;
// the cells (i, j, k) and (i, j, k+1) are adjacent in memory
// the rows (i, j, _) and (i, j+1, _) are adjacent in memory
// the "slices" (i, _, _) and (i+1, _, _) are adjacent in memory
constexpr index_t cell_index(index_t i, index_t j, index_t k) {
return (i * height + j) * depth + k;
}
int main() {
int* array = new int[width * height * depth]();
for( index_t i = 0 ; i < width ; ++i )
for( index_t j = 0 ; j < height ; ++j )
for( index_t k = 0 ; k < depth ; ++k ) {
// do something on the cell (i, j, k)
array[cell_index(i, j, k)] = i + j + k;
std::cout << array[cell_index(i, j, k)] << ' ';
}
std::cout << '\n';
// alternatively you can do this:
//*
for( index_t index = 0 ; index < width * height * depth ; ++index) {
index_t i = index / (height * depth);
index_t j = (index / depth) % height;
index_t k = index % depth;
array[index] = i + j + k;
std::cout << array[index] << ' ';
}
std::cout << '\n';
//*/
delete[] array;
}
The difference is the organization in memory. Here you have a big block of 60*sizeof(int) bytes (usually 240 or 480 bytes), whereas with your method you would have:
- 1 block of 3*sizeof(int**) bytes
- 3 blocks of 4*sizeof(int*) bytes
- 12 blocks of 5*sizeof(int) bytes
(120 more bytes on a 64 bit architecture, two additional indirections for each cell access, and more code for allocating/deallocating all that memory)
Granted, you can't do array[i][j][k] anymore, but still...
The same stands with vectors (you can either make an std::vector<std::vector<std::vector<int>>> or a std::vector<int>)
There is also a bit too much code repetition: your algorithm basically swaps the two halves of your table three times (once for each dimension), but you rewrote 3 times the same thing with a few differences.
There is also too much memory allocation/copy (your algorithm works and can exploit the structure of array of pointers by simply swapping pointers to swap whole rows/slices, in that specific case, you can exploit this data structure to avoid copies with your algorithm... but you don't)
You should choose more explicit variable names, that helps. For instance use width, height, depth instead of a, b, c.
For instance, here is an implementation with vectors (I didn't know matlab's fftshift function though, but according to your code and this page, I assume it's basically "swapping the corners"):
(also, compile with -std=c++11)
#include <cstddef>
#include <iostream>
#include <vector>
#include <algorithm>
typedef std::size_t index_t;
typedef double element_t;
typedef std::vector<element_t> row_t;
typedef std::vector<row_t> slice_t;
typedef std::vector<slice_t> array_3d_t;
// for one dimension
// you might overload this for a std::vector<double>& and use memmove
// as you originally wanted to do here
template<class T>
void fftshift_dimension(std::vector<T>& row)
{
using std::swap;
const index_t size = row.size();
if(size <= 1)
return;
const index_t halved_size = size / 2;
// swap the two halves
for(index_t i = 0, j = size - halved_size ; i < halved_size ; ++i, ++j)
swap(row[i], row[j]);
// if the size is odd, rotate the right part
if(size % 2)
{
swap(row[halved_size], row[size - 1]);
const index_t n = size - 2;
for(index_t i = halved_size ; i < n ; ++i)
swap(row[i], row[i + 1]);
}
}
// base case
template<class T>
void fftshift(std::vector<T>& array) {
fftshift_dimension(array);
}
// reduce the problem for a dimension N+1 to a dimension N
template<class T>
void fftshift(std::vector<std::vector<T>>& array) {
fftshift_dimension(array);
for(auto& slice : array)
fftshift(slice);
}
// overloads operator<< to print a 3-dimensional array
std::ostream& operator<<(std::ostream& output, const array_3d_t& input) {
const index_t width = input.size();
for(index_t i = 0; i < width ; i++)
{
const index_t height = input[i].size();
for(index_t j = 0; j < height ; j++)
{
const index_t depth = input[i][j].size();
for(index_t k = 0; k < depth; k++)
output << input[i][j][k] << ' ';
output << '\n';
}
output << '\n';
}
return output;
}
int main()
{
constexpr index_t width = 3;
constexpr index_t height = 4;
constexpr index_t depth = 5;
array_3d_t input(width, slice_t(height, row_t(depth)));
// initialization
for(index_t i = 0 ; i < width ; ++i)
for(index_t j = 0 ; j < height ; ++j)
for(index_t k = 0 ; k < depth ; ++k)
input[i][j][k] = i + j + k;
std::cout << input;
// in place fftshift
fftshift(input);
std::cout << "and then" << '\n' << input;
}
live example
You could probably make a slightly more efficient algorithm by avoiding to swap multiple times the same cell and/or using memmove, but I think it's already fast enough for many uses (on my machine fftshift takes roughly 130ms for a 1000x1000x100 table).
I'm trying to develop a wordsearch which finds the word "OIE" (indicating how many times appears), based in an integer unidimensional array that saves the directions (8), but I get strange errors when I run this (and incorrect outputs).
This is the code:
int arrf[8] = {0, -1, -1, -1, 0, 1, 1, 1};
int arrc[8] = {-1, -1, 0, 1, 1, 1, 0,-1};
char s[] = "OIE";
int main() {
int n, m;
while (cin >> n >> m) {
int res = 0;
vector<vector<char> > S(n, vector<char>(m));
for (int i = 0; i < n; ++i) for (int j = 0; j < m; ++j) cin >> S[i][j];
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
for (int d = 0; d < 8; ++d) {
bool trobat = true;
for (int h = 0; h < 3 and trobat; ++h) {
int f = i + arrf[d], c = j + arrc[d];
if (f < 0 || f >= n || c < 0 || c >= m || S[f][c] != s[h])
trobat = false;
}
if (trobat) res++;
}
}
}
cout << res << endl;
}
}
Could somebody help me to fix this? I would appreciate.
Regards.
One error is that this line
int f = i + arrf[d], c = j + arrc[d];
should be
int f = i + h*arrf[d], c = j + h*arrc[d];
With your code it doesn't matter how many times you go round the inner loop you are still checking the same position.