Good day,
I need a help. We get a homework to write a programme in C which should generate and print bigger and smaller matrix made from "X" and ".". And after that find if the smaller 3x3 matrix is in the bigger one. I tried to make it by one dimensional field, but my programme finds matrix only sometimes. I am not able to find it out where is my mistake and how to fix it. I read some threads on forum, but none of it was helpfull to me. Thanks for any help.
P.S. Forgive me language mistakes, I am not a native english speaker.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Generates matrix of given dimensions */
void initMatrix(char *Matrix, int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
Matrix[i*cols+j]= "X.." [rand () % 3]; // 2/3 that X will be generated
}
}
}
/* Prints given matrix */
void printMatrix(char *Matrix, int rows, int cols)
{
for(int i = 0; i < rows; i++)
{
for(int j = 0; j < cols; j++)
{
printf("%c", Matrix[i * cols + j]);
}
printf("\n");
}
}
int main(void)
{
int rowM1, colM1; // Dimensions of primary (bigger) matrix
int rowM2 = 3, colM2 = 3; // Dimensions of secondary (smaller) matrix
int first, second; // Position of the begginng of matrix 2 in matrix 1
int rel_pos;
int i, j, k, l;
char *M1 = NULL; // Pointer to matrix 1
char *M2 = NULL; // Pointer to matrix 2
printf("Enter the matrix dimensions separated by a space ([rows] [columns]) : ");
if (scanf("%d %d", &rowM1, &colM1) != 2) // Bad parameters
{
printf("Wrong parameters.");
return 1; // End program
}
if (rowM1 < rowM2 || colM1 < colM2)
{
printf("Matrix 2 can not be found because is bigger than Matrix 1.");
return 1;
}
srand(time(NULL)); // Randomly generates numbers
M1 = malloc(rowM1 * colM1 * sizeof(char)); // M1 points to matrix 1
M2 = malloc(rowM2 * colM2 * sizeof(char)); // M2 points to matrix 2
initMatrix(M1, rowM1, colM1); // Initializes matrix 1
initMatrix(M2, rowM2, colM2); // Initializes matrix 2
printf("\nMatrix 1:\n");
printMatrix(M1, rowM1, colM1); // Prints matrix 1
printf("\nMatrix 2:\n");
printMatrix(M2, rowM2, colM2); // Prints matrix 2
putchar('\n');
for (i = 0; i < rowM1; i++)
{
for(j = 0; j < colM1; j++){
{
for (k = 0; k < rowM2 * colM2; k++) // checking the smaller matrix
{
if(M1[i*rowM1+j] == M2[k])
{
first = i*rowM1;
rel_pos = i+1;
}
if(j % colM2 == 0) // Matrix 2 has ended on this line, move on next one.
rel_pos += colM1 - colM2;
if(M1[rel_pos] == M2[j]) // If character are same, keep searching
rel_pos++;
else // else this is not the matrix I'm searching for
break;
}
if(k == rowM2*colM2) // if all k cykle went to the end I found the matrix
{
printf("Matrix found at [%d][%d]", first, second);
return 0;
}
}
}
if(i*colM1 > i*colM1-colM2) // matrix cannot be found
printf("Matrix not found");
break;
}
free(M1); // frees memory of matrix 1
free(M2); // frees memory of matrix 2
return 0;
}
Your inner loop for (k = 0; k < rowM2 * colM2; k++) iterates over the contents of the small matrix, and should compare each entry of the small matrix to the corresponding entry in the large matrix (as defined by the start point given by i and j).
The comparison if(M1[i*rowM1+j] == M2[k]), however, compares all entries of the small matrix with the same entry in the large matrix (the array index of M1 is independent of k).
To fix this, you need to make a fourdimensional loop
for(y0 = 0; y0 < colM1 - colM2 + 1; y0++) {
for(x0 = 0; x0 < rowM1 - rowM2 + 1; x0++) {
for(dy = 0; dy < colM2; dy++) {
for(dx = 0; dx < rowM2; dx++) {
if(M1[(y0 + dy)*rowM1 + (x0 + dx)] == M2[dy*rowM2 + dx]) {
...
}
}
}
}
}
Related
I'm sorry to ask help for a HackerRank problem here, I know it's not really the right place but nobody is answering me on HackerRank. Also, I'm new in C, so don't be to rude please.
Problem's description:
You are given n triangles, specifically, their sides a, b and c. Print them in the same style but sorted by their areas from the smallest one to the largest one. It is guaranteed that all the areas are different.
Link to the problem : https://www.hackerrank.com/challenges/small-triangles-large-triangles/problem
We can only edit the sort_by_area function.
First of all, I didn't calculate the triangles' area, I've just calculated the perimeter of each triangle, because the formula is simpler to read and to execute. Normally, that doesn't change anything for the result since a bigger perimeter means a bigger area. Tell me if I'm wrong.
The problem is that I have unexpected results: there's numbers on a line from my output that I really don't know from where they come. See:
Code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(100 * sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
temp = tr[j].a;
tr[j].a = tr[j + 1].a;
tr[j + 1].a = temp;
temp = tr[j].b;
tr[j].b = tr[j + 1].b;
tr[j + 1].b = temp;
temp = tr[j].c;
tr[j].c = tr[j + 1].c;
tr[j + 1].c = temp;
}
}
}
}
int main() {
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}
Input:
3
7 24 25
5 12 13
3 4 5
Output:
0 417 0 // Unexpected results on this line.
3 4 5
5 12 13
Expected output:
3 4 5
5 12 13
7 24 25
It seems that an error occurs from the 7 24 25 triangle, but for me, my code seems to be good.... Can you help to find out what's wrong ? I really want to understand before going to another problem.
The assumption that a greater parameter implies a greater area is incorrect. Why? Imagine an isosceles triangle with a base of 1000 units and a height of 1e-9 units. The area is minuscule, compared to an equilateral triangle with unit length whereas the former has a huge perimeter (~2000 units) compared to the latter (3 units). That's just an (extreme) example to convey the flaw in your assumption.
I'd suggest you roll up your own area function. It's even mentioned on the problem page to use Heron's formula. Since it's just to be used in the comparison, then we don't need the exact area but an indicative area. So something like
double area(triangle const* tr) {
if(tr) {
double semiPerimeter = (tr->a + tr->b + tr->c)/2.0;
return semiPerimeter* (semiPerimeter - tr->a) * (semiPerimeter - tr->b) * (semiPerimeter - tr->c);
} else {
return 0;
}
}
Where we don't really need to calculate the square root since we just need to compare the areas across triangles and comparing the square of areas across triangles should be fine.
After this, it's just a matter of plugging this into whatever you did, after correcting the inner j loop to run only till n-1 (as the other answer has also explained)
void sort_by_area(triangle* tr, int n) {
/**
* Sort an array a of the length n
*/
double areaArr[n];
for(size_t i = 0; i < n; ++i) {
areaArr[i] = area(&tr[i]);
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (areaArr[j] > areaArr[j + 1]) {
// Sort in area array.
int temp = areaArr[j];
areaArr[j] = areaArr[j + 1];
areaArr[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
You could directly use qsort too here since the problem doesn't prohibit using standard functions, something like:
int qsortCompare(void const* a, void const* b) {
triangle const* trA = a;
triangle const* trB = b;
if(trA && trB) {
double areaA = area(trA);
double areaB = area(trB);
return (areaA < areaB) ? -1 :
((areaA > areaB)? 1: 0);
}
return 0;
}
void sort_by_area(triangle* tr, int n) {
qsort(tr, n, sizeof(triangle), &qsortCompare);
}
Also, don't be restricted to add functions in the problem solution. The actual driver code only calls sort_by_area() but you can write other functions in the solution and call them from sort_by_area().
The inner loop does not need to run till n, only till n-1
for (int j = 0; j < n - 1; j++)
Because when j == n, then you are comparing with random junk outside of your respective arrays by accessing size[j+1] and tr[j+1].
Also, when swapping, you don't need to copy the structure members one-by-one. You can simply do:
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
Edit: As #CiaPan pointed out:
You have a memory leak. You need to call free() after you are done with using the malloc'd memory.
You are not allocating the right amount of memory. If you are passed more than 100 triangles, your code might behave weirdly or randomly crash.
int *size = malloc(n* sizeof(*size));
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
typedef struct {
int a;
int b;
int c;
} triangle;
void sort_by_area(triangle *tr, int n) {
// Array for storing the perimeter.
int *size = malloc(n* sizeof(*size));
// Adding perimeters in size array.
for (int i = 0; i < n; i++) {
size[i] = tr[i].a + tr[i].b + tr[i].c;
}
// Sort.
for (int i = 0; i < n; i++) {
for (int j = 0; j < n - 1; j++) {
if (size[j] > size[j + 1]) {
// Sort in size array.
int temp = size[j];
size[j] = size[j + 1];
size[j + 1] = temp;
// Sort in tr array.
triangle tmp = tr[j];
tr[j] = tr[j + 1];
tr[j + 1] = tmp;
}
}
}
}
int main() {
int n;
scanf("%d", &n);
triangle *tr = malloc(n * sizeof(triangle));
for (int i = 0; i < n; i++) {
scanf("%d%d%d", &tr[i].a, &tr[i].b, &tr[i].c);
}
sort_by_area(tr, n);
for (int i = 0; i < n; i++) {
printf("%d %d %d\n", tr[i].a, tr[i].b, tr[i].c);
}
return 0;
}
I'm having issues getting a function to work which should find the determinant of an upper triangular matrix. My code seems to return clearly incorrect values, usually zero and I'm pretty certain that this is caused by me defining the function incorrectly some how. I suspect it is a basic error on my part but after staring at it for sometime I havent managed to figure it out. Here is the function and printing code:
int Determinant(int mat[20][20],int N)
{
int X=0,Det=0;
if (N==2){
Det=mat[0][0]*mat[1][1]-mat[0][1]*mat[1][0];
return(Det);
}
else {
for(X = 0; X < N; X++){
Det *= mat[X][X];
}
}
return (Det);
}
and the print function :
determinant=Determinant(matrix,n);
printf("Determinant = %d",determinant);
I'll include the full code that I've written so far to provide more detail. It's basic application at the moment is to define and n by n matrix (2
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int determinant(int mat[20][20],int N);
int Determinant(int mat[20][20],int N)
{
int X=0,Det=0;
if (N==2){
Det=mat[0][0]*mat[1][1]-mat[0][1]*mat[1][0];
return(Det);
}
else {
for(X = 0; X < N; X++){
Det *= mat[X][X];
}
}
return (Det);
}
int main()
{
int n=0,i=1;
printf("Please enter a number (n) between 2 and 4 to determine the dimensions of an (nxn) matrix \n");
scanf("%d",&n);
while(n<2||n>4){
printf("The value %d does not lie within the required range of 2-4, please re-enter \n",n);
scanf("%d",&n);
i++;
if (i>=3){
printf("\nYou have entered invalid values 3 times. The programme has been terminated");
exit(0);
}
}
printf("\n(%dx%d) matrix selected\n",n,n);
int matrix[n][n];
int f,g=0;
printf("Please enter matrix elements\n");
for(f=0;f<n;f++){
for(g=0;g<n;g++){
printf("Element[%d][%d] = ",f,g);
scanf("%d",&matrix[f][g]);
}
}
int k,j;
printf("\nThe matrix is\n");
for(k=0;k<n;k++){
printf("\n");
for(j=0;j<n;j++){
printf("%d\t",matrix[k][j]);
}
}
int temp=0,c=0,determinant=0;
float factor=0;
k=0;
/* Transform matrix into upper triangular */
for(i = 0; i < n - 1; i++)
{
/* Elementary Row Operation I */
if(matrix[i][i] == 0)
{
for(k = i; k < n; k++)
{
if(matrix[k][i] != 0)
{
for(j = 0; j < n; j++)
{
temp = matrix[i][j];
matrix[i][j] = matrix[k][j];
matrix[k][j] = temp;
}
k = n;
}
}
c++;
}
/* Elementary Row Operation III */
if(matrix[i][i] != 0)
{
for(k = i + 1; k < n; k++)
{
factor = -1.0 * matrix[k][i] / matrix[i][i];
for(j = i; j < n; j++)
{
matrix[k][j] = matrix[k][j] + (factor * matrix[i][j]);
}
}
}
}
printf("\nThe Upper triangular is\n");
for(k=0;k<n;k++){
printf("\n");
for(j=0;j<n;j++){
printf("%d\t",matrix[k][j]);
}
}
determinant=Determinant(matrix,n);
printf("Determinant = %d",determinant);
/*
*/
return 0;
}
The problem is basically the way you pass the matrix as a parameter. To see what I mean, change the definition of the function to read:
int Determinant(int mat[5][5],int N);
and instruct the function body to print the full 5x5 matrix passed:
int Determinant(int mat[5][5],int N)
{
printf("\n");
int a,b;
for(a = 0; a < 5; a++)
{
for(b = 0; b < 5; b++)
{
printf("%d\t", mat[a][b]);
}
printf("\n");
}
int X=0,Det=0;
Det = 1; // Add this too!
for(X = 0; X < N; X++) {
Det *= mat[X][X];
}
return (Det);
}
Now enter n=3 for the matrix dimension and pass the already upper triangular matrix
1 2 3
0 4 5
0 0 6
Observe the printout of the matrix passed in the Determinant() function, it will be something like this:
1 2 3 0 4
5 0 0 6 0
4196432 0 -163754450 0 -1253168992
32764 3 0 0 0
3 0 0 0 3
This means that your array has been "reshaped", and your actual data are stored in consecutive places in memory, unlike the original array.
TLDR: Although I am not very proficient with C, I think that you should define your 2d array as a dynamic one (for example using a double pointer).
PS: Don't forget to initialize Det variable to 1 instead of 0 in the function body, otherwise the product will always equal 0.
How to normalize a matrix?
Suppose I have a 2x3 matrix:
1 2 3
4 5 6
The normalized matrix would be:
1/sqrt(pow(2,2) + pow(3,2)) 2/sqrt(pow(2,2) + pow(3,2)) 3/sqrt(pow(2,2) + pow(3,2))
4/sqrt(pow(5,2) + pow(6,2)) 5/sqrt(pow(5,2) + pow(6,2)) 6/sqrt(pow(5,2) + pow(6,2))
This is my sample code:
#include <stdio.h>
#include <conio.h>
#include <math.h>
int main(){
int rows, cols, rowCounter, colCounter, r, c;
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for(rowCounter = 0; rowCounter < rows; rowCounter++){
for(colCounter = 0; colCounter < cols; colCounter++){
scanf("%d", &inputMatrix[rowCounter][colCounter]);
}
}
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c];
square[r] += pow(a, 2);
}
printf("%.2lf ", square[r]);
}
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
}
}
printf("\nNormalized Matrix:\n");
for(rowCounter = 0; rowCounter < rows; rowCounter++)
{
for(colCounter = 0; colCounter < cols; colCounter++)
{
printf("%.3lf ", norm[rowCounter][colCounter]);
}
printf("\n");
}
getch();
return 0;
}
Why are you using == here:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a == inputMatrix[r][c]; //look here
square[r] += pow(a, 2);
}
It should be:
for(r = 0; r < rows; r++)
{
for(c = 1; c < cols; c++)
{
float a;
a = inputMatrix[r][c];
square[r] += pow(a, 2);
}
The same here:
norm[rowCounter][colCounter] == (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
It should be:
norm[rowCounter][colCounter] = (inputMatrix[rowCounter][colCounter]) / sqrt(square[rowCounter]);
And you should be careful here:
int initial[100], inputMatrix[100][100], rowSum[100] = {0}, norm[100][100], square[100] = {0};
Are you sure about use int for all of this declarations?
I think you should use double or float instead, at least in some of them.
There are some problems in your code, I'll try to address the most important ones.
Your norm matrix is a 2D array of int as inputMatrix, but you have to use an array of float or double to correctly store the result and to perform the right calculation. In C if both of the terms of a division are integers types an integer division (like: 3/2 = 1, not 1.5) is performed, which is not what you need.
Another mistake is to use == instead of = to perform an assignment. In C == is the 'equal to' relational operation.
EDIT
As #chux pointed out it would be wiser to choose a more accurate type for a and square[]. Using long long int will (may) prevent numeric overflow in case the elements of the matrix are too big for their square or the sum of them to be reprensented by an int.
Be aware that if you decide to use double instead there are other subtle numerical issues concernig the sum of small number (and the order in which it is performed) represented by floating point types. So, as a partial remedy, you can use long double (if it really has more precision then double in your environment) for a and square.
EDIT 2
In the question and in comment you say that the first element of each row of the matrix is supposed to be "constant in the matrix" so it doesn't take part to the sum of squares in your code and in the example you gave, but in both of them they are updated in the next loop. I'm not sure of what is going on, so I corrected my code to mimic the behavior of yours.
Here is a working corrected version of your code:
#include <stdio.h>
#include <math.h>
int main() {
int rows, cols, r, c;
// you may think about dynamical allocation here
int inputMatrix[100][100], rowSum[100] = {0};
// it's better to use a type that can manage bigger numbers to avoid numeric overflow
long long int a, square[100] = {0};
// your starting matrix can be a matrix of int but the normalized one need to
// contain floating point numbers
double norm[100][100], k;
printf("Enter size of a matrix\n");
scanf("%d %d", &rows, &cols);
printf("Enter matrix of size %dX%d\n", rows, cols);
/* Input matrix */
for ( r = 0; r < rows; r++) {
for (c = 0; c < cols; c++) {
scanf("%d", &inputMatrix[r][c]);
// ^^ if you are scanning integer numbers...
}
}
printf("\nrows: %d cols: %d elements:\n",rows,cols);
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%d ", inputMatrix[r][c]);
// ... ^^ you should print integer numbers
}
printf("\n");
}
for (r = 0; r < rows; r++) {
for (c = 1; c < cols; c++) {
// ^^^ I don't know why you skip this here
a = inputMatrix[r][c];
//^ You have to assign, not to compare!
square[r] += a * a;
// ^^^^^ no need to call pow()
}
printf("Sum of squares of row %d: %lld\n",r,square[r]);
// square contains int ^^
// It would be nice and safer if you check here if square == 0 to avoid a
// division by zero and probably detect bad input data
}
for ( r = 0; r < rows; r++ ) {
// It's far more efficient to precalculate this term, even if compilers
// could be smart enough to do it for you. You may want to store those
// values in an array of doubles instead of the (sum of) squares
k = 1.0 / sqrt(square[r]);
for( c = 0; c < cols; c++ ) {
norm[r][c] = k * inputMatrix[r][c] ;
// again, ^ assign not compare
}
}
// you can add the printf to the previous loop...
printf("\nNormalized Matrix:\n");
for( r = 0; r < rows; r++) {
for( c = 0; c < cols; c++) {
printf("%.3lf ", norm[r][c]);
// ^^^^^ norm contains double
}
printf("\n");
}
return 0;
}
I keep the input matrix of integer type, but it would be better to use double for that too. As i added a print loop for the original matrix, the final output is:
rows: 2 cols: 3 elements:
1 2 3
4 5 6
Sum of squares of row 0: 13
Sum of squares of row 1: 61
Normalized Matrix:
0.277 0.555 0.832
0.512 0.640 0.768
I want to store a lower triangular matrix in memory, without storing all the zeros.
The way I have implemented it is by allocating space for i + 1 elements on the ith row.
However, I am new to dynamic memory allocation in C and something seems to be wrong with my first allocation.
int main ()
{
int i, j;
int **mat1;
int dim;
scanf("%d", &dim);
*mat1 = (int**) calloc(dim, sizeof(int*));
for(i = 0; i < dim; i++)
mat1[i] = (int*) calloc(i + 1, sizeof(int));
for(i = 0; i < dim; i++)
{
for(j = 0; j < i + 1; j++)
{
scanf("%d", &mat1[i][j]);
}
}
/* Print the matrix without the zeros*/
for(i = 0; i < dim; i++)
{
for(j = 0; j < (i + 1); j++)
{
printf("%d%c", mat1[i][j], j != (dim-1) ? ' ' : '\n');
}
}
return 0;
}
If you want to conserve space and the overhead of allocating every row of the matrix, you could implement a triangular matrix by using clever indexing of a single array.
A lower triangular matrix (including diagonals) has the following properties:
Dimension Matrix Elements/row Total elements
1 x . . . 1 1
2 x x . . 2 3
3 x x x . 3 6
4 x x x x 4 10
...
The total number of elements for a given dimension is:
size(d) = 1 + 2 + 3 + ... + d = (d+1)(d/2)
If you lay the rows out consecutively in a single array, you can use the formula above to calculate the offset of a given row and column (both zero-based) inside the matrix:
index(r,c) = size(r-1) + c
The formulas above are for the lower triangular matrix. You can access the upper matrix as if it was a lower matrix by simply reversing the indexes:
index((d-1)-r, (d-1)-c)
If you have concerns about changing the orientation of the array, you can devise a different offset calculation for the upper array, such as:
uindex(r,c) = size(d)-size(d-r) + c-r
Sample code:
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define TRM_SIZE(dim) (((dim)*(dim+1))/2)
#define TRM_OFFSET(r,c) (TRM_SIZE((r)-1)+(c))
#define TRM_INDEX(m,r,c) ((r)<(c) ? 0 : (m)[TRM_OFFSET((r),(c))])
#define TRM_UINDEX(m,r,c,d) ((r)>(c)?0:(m)[TRM_SIZE(d)-TRM_SIZE((d)-(r))+(c)-(r)])
#define UMACRO 0
int main (void)
{
int i, j, k, dimension;
int *ml, *mu, *mr;
printf ("Enter dimension: ");
if (!scanf ("%2d", &dimension)) {
return 1;
}
ml = calloc (TRM_SIZE(dimension), sizeof *ml);
mu = calloc (TRM_SIZE(dimension), sizeof *mu);
mr = calloc (dimension*dimension, sizeof *mr);
if (!ml || !mu || !mr) {
free (ml);
free (mu);
free (mr);
return 2;
}
/* Initialization */
srand (time (0));
for (i = 0; i < TRM_SIZE(dimension); i++) {
ml[i] = 100.0*rand() / RAND_MAX;
mu[i] = 100.0*rand() / RAND_MAX;
}
/* Multiplication */
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
for (k = 0; k < dimension; k++) {
mr[i*dimension + j] +=
#if UMACRO
TRM_INDEX(ml, i, k) *
TRM_UINDEX(mu, k, j, dimension);
#else
TRM_INDEX(ml, i, k) *
TRM_INDEX(mu, dimension-1-k, dimension-1-j);
#endif
}
}
}
/* Output */
puts ("Lower array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %2d", TRM_INDEX(ml, i, j));
}
putchar ('\n');
}
puts ("Upper array");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
#if UMACRO
printf (" %2d", TRM_UINDEX(mu, i, j, dimension));
#else
printf (" %2d", TRM_INDEX(mu, dimension-1-i, dimension-1-j));
#endif
}
putchar ('\n');
}
puts ("Result");
for (i = 0; i < dimension; i++) {
for (j = 0; j < dimension; j++) {
printf (" %5d", mr[i*dimension + j]);
}
putchar ('\n');
}
free (mu);
free (ml);
free (mr);
return 0;
}
Note that this is a trivial example. You could extend it to wrap the matrix pointer inside a structure that also stores the type of the matrix (upper or lower triangular, or square) and the dimensions, and write access functions that operate appropriately depending on the type of matrix.
For any non-trivial use of matrices, you should probably use a third-party library that specializes in matrices.
mat1 = calloc(dim,sizeof(int*));
mat1 is a double pointer.You need to allocate memory for your array of pointers and later you need to allocate memory to each of your pointers individually.No need to cast calloc()
You are dereferencing mat1 at line 8 before it has even been set to point anywhere. You are allocating an array of pointers to int, but you are not assigning that to mat1 but to the dereference of mat1, which is uninitialized, we don't know what it points to.
So this line:
// ERROR: You are saying an unknown memory location should have the value of calloc.
*mat1 = (int**)calloc(dim,sizeof(int*));
Should change to:
// OK: Now you are assigning the allocation to the pointer variable.
mat1 = (int**)calloc(dim,sizeof(int*));
I was trying to calculate the determinant of a 3 * 3 matrix (or more) with the matrix values ranging from (-1, to 1). However, I get a result of 0 when I calculate the determinant.
[...]
srand(time(NULL));
//Random generation of values between -1 and 1
for(i = 0; i < 3; i++)
{
for(j = 0; j < 3; j++)
{
temp = (rand() % (500)) + 0;
temp = temp/250;
array[i][j] = (temp - 1);
}
[...]
double array2[10][10];
double detrm = 0;
int s = 1;
int i, j, m, n, c;
for (c = 0; c < x; c++)
{
m = 0;
n = 0;
for (i = 0; i < x; i++)
{
for (j = 0; j < x; j++)
{
array2[i][j] = 0;
if (i != 0 && j != c)
{
array2[m][n] = a[i][j];
if ( n < (x - 2))
{
n++;
}
else
{
n = 0;
m++;
}
}
}
}
detrm = detrm + (s*a[0][c]*determinant(array2, (x - 1)));
s = -1*s;
}
return(detrm);
This may Help - see comments within the code for an explanation:
static int CalcDeterminant(vector<vector<int>> Matrix)
{
//this function is written in c++ to calculate the determinant of matrix
// it's a recursive function that can handle matrix of any dimension
int det = 0; // the determinant value will be stored here
if (Matrix.size() == 1)
{
return Matrix[0][0]; // no calculation needed
}
else if (Matrix.size() == 2)
{
//in this case we calculate the determinant of a 2-dimensional matrix in a
//default procedure
det = (Matrix[0][0] * Matrix[1][1] - Matrix[0][1] * Matrix[1][0]);
return det;
}
else
{
//in this case we calculate the determinant of a squared matrix that have
// for example 3x3 order greater than 2
for (int p = 0; p < Matrix[0].size(); p++)
{
//this loop iterate on each elements of the first row in the matrix.
//at each element we cancel the row and column it exist in
//and form a matrix from the rest of the elements in the matrix
vector<vector<int>> TempMatrix; // to hold the shaped matrix;
for (int i = 1; i < Matrix.size(); i++)
{
// iteration will start from row one cancelling the first row values
vector<int> TempRow;
for (int j = 0; j < Matrix[i].size(); j++)
{
// iteration will pass all cells of the i row excluding the j
//value that match p column
if (j != p)
{
TempRow.push_back(Matrix[i][j]);//add current cell to TempRow
}
}
if (TempRow.size() > 0)
TempMatrix.push_back(TempRow);
//after adding each row of the new matrix to the vector tempx
//we add it to the vector temp which is the vector where the new
//matrix will be formed
}
det = det + Matrix[0][p] * pow(-1, p) * CalcDeterminant(TempMatrix);
//then we calculate the value of determinant by using a recursive way
//where we re-call the function by passing to it the new formed matrix
//we keep doing this until we get our determinant
}
return det;
}
}
};
You have a crufty way of updating m and n. You should increment m in the outer loop over i, and initialize n within the outer loop and increment it within the inner loop. I think that your code would work as you wrote it, but I think that your conditional should have been i < n-1 instead of i < n-2. But instead of changing the fewest number of characters to get the code to work, I recommend restructuring the increments so that the issue doesn't arise.