Skipping Diagonal Elements Within a Square Matrix - c

Wrote a program to display a square matrix (ex: 5x5) and I am trying to count the total of the elements excluding the elements that lie within a diagonal line (from top left to bottom right & from bottom left to top right)
EX:
In a 5x5 matrix, only the Xs would be counted
O X X X O
X O X O X
X X O X X
X O X O X
O X X X O
Thus:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
Total: 16
OR
2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
2 2 2 2 2
Total: 32
Here is my code
int calculateVal(int **mat, int size)
{
int count = 0;
for (int row = 0; row < size; row++)
{
for (int col = 0; col < size; col++)
{
if (isRightDiagonal(size, row, col) == true ||
isLeftDiagonal(size, row, col) == true)
{
col++;
}
count += mat[row][col];
}
}
return count;
}
bool isRightDiagonal(int size, int row, int col)
{
return (col = abs(row - size)) ? true : false;
}
bool isLeftDiagonal(int size, int row, int col)
{
return (row = abs(col - size)) ? true : false;
}
I tried using an if statement to check if the element is within a diagonal, and if so, skipping to the next element, but the output is wrong.
The test case I have been primarily using is a 5x5 of 1s like the example above; however, the total prints out as 10 rather than 16

The tests for the diagonals are incorrect:
an element is part of the left diagonal if col == row
an element is part of the right diagonal if size - 1 - col == row
Furthermore, if the element is part of either diagonal, it should just be ignored, incrementing col is incorrect as it may make mat[row][col] refer en element outside the matrix, causing undefined behavior.
Here is a modified version:
int calculateVal(int **mat, int size) {
int count = 0;
for (int row = 0; row < size; row++) {
for (int col = 0; col < size; col++) {
if (col != row && size - 1 - col != row) {
count += mat[row][col];
}
}
}
return count;
}

Using a sample matrix with 1 for the entries you don't want to count (if you sum them instead of count then the value is not 0 then you know something is off). You could use a similar crafted matrix to ensure that the the 16 entries you are interested in are counted:
#include <stdio.h>
#include <stdlib.h>
int main() {
int matrix[][5] = {
{1, 0, 0, 0, 1},
{0, 1, 0, 1, 0},
{0, 0, 1, 0, 0},
{0, 1, 0, 1, 0},
{1, 0, 0, 0, 1}
};
size_t sum = 0;
const size_t n = sizeof matrix / sizeof *matrix;
for(size_t r = 0; r < n; r++)
for(size_t c = 0; c < n; c++)
sum += (r != c && r + c + 1 != n) * matrix[r][c];
printf("sum = %zu\n", sum);
}
If you don't like the non-branching style here is another way to express it:
if(r != c && r + c + 1 != n)
sum += matrix[r][c];

Related

C Program- How to find sum of middle elements in a matrix?

Given a 2-Dimensional Array, sum up all the numbers that are not on the edges of the 2-D array.
Example 2-D Array:
5 7 1 6
2 6 1 8
1 5 4 7
5 8 9 1
4 4 5 1
The numbers added should only be 6+1+5+4+8+9.
int rows, cols,s1=0,s2=0;
printf("Enter number of rows: ");
scanf("%d", &rows);
printf("Enter number of columns: ");
scanf("%d", &cols);
int matrix[rows][cols];
printf("Elements:\n");
for(int row = 0; row < rows; row++){
for(int col = 0; col < cols; col++){
scanf("%d", &matrix[row][col]);
}
}
printf(Sum: %d", __);
......
Write a function:
static int sum_middle(int rows, int cols, int matrix[rows][cols])
{
int sum = 0;
for (int r = 1; r < rows - 1; r++)
{
for (int c = 1; c < cols - 1; c++)
sum += matrix[r][c];
}
return sum;
}
Then call it after your input loops:
int sum = sum_middle(rows, cols, matrix);
You could change your input functionality to calculate the sum as you go along:
int sum = 0;
for(int row = 0; row < rows; row++){
for(int col = 0; col < cols; col++){
scanf("%d", &matrix[row][col]);
if(
row && (rows > 2) && (row + 1) != rows &&
col && (cols > 2) && (col + 1) != cols
)
sum += matrix[row][col];
}
}
Or you could do this in a 2nd loop (see #JonathanLeffler's answer). This would allow you to do the rows and cols check only once instead of per iteration (i.e. if rows = INT_MAX and cols is 0, 1 or 2).
Let me explain you how to do this in pseudo-code:
You need to sum all numbers which don't pass a certain criteria. There are two ways to do this:
Sum all number which don't pass a certain criteria. This can be done if the criteria is not too difficult.
Sum all numbers. Sum all numbers who pass a certain criteria and subtract that from the first sum.
Let's see if we can accomplish in the first way: we start by summing all numbers:
sum = 0
for i = 0 to a-1:
for j = 0 to b-1:
sum += matrix[i,j];
next j
next i
Now we need to add the criteria:
sum = 0
for i = 0 to a-1:
for j = 0 to b-1:
if not(criteria(i,j))
then sum += matrix[i,j];
next j
next i
But what is the criteria: how to you say (i,j) belongs to an edge?
Well, that's quite simple: the edges mean that i equals either 0 or a, and j equals 0 or b:
So you write a function criteria(i,j) as follows:
boolean criteria(i,j):
return ((i == 0) OR (i == a)) AND
((j == 0) OR (j == b));
Or, as the criteria is so simple, you don't even need a function for this:
sum = 0
for i = 0 to a-1:
for j = 0 to b-1:
if not(((i == 0) OR (i == a)) AND
((j == 0) OR (j == b)))
then sum += matrix[i,j];
next j
next i
But as you might expect, there's an easier way to write the criteria, using not(x AND y) = not(x) OR not(y) and not (x OR y) = not(x) AND not(y), but this one I leave to you :-)

how to print a matrix with a negated row more efficiently

I wrote the following function:
void negate_row(const int n, const int r, int *a)
{
if (r == 0)
{
printf("Matrix with negated row: ");
printf("\n");
for (int y = 0; y < 3; y++)
{
*(a + 3 * r + y) = *(a + 3 * r + y) *(-1);
printf("%d ", *(a + 3 * r + y));
}
printf("\n");
for (int y = 0; y < 3; y++)
{
*(a + 3 * r + y) = *(a + 3 * r + y) *(-1);
printf("%d ", *(a + 3 * (r + 1) + y));
}
printf("\n");
for (int y = 0; y < 3; y++)
{
*(a + 3 * r + y) = *(a + 3 * r + y) *(-1);
printf("%d ", *(a + 3 * (r + 2) + y));
}
printf("\n");
}
So basically what happens here is my function takes in a n X 3 matrix and negates a specific row using pointer arithmetic. I have been able to achieve that, I've also been able to figure out how to print that same matrix with the negated row. It's just the way I'm doing it is not efficient at all. I'd have to write an if statement for each row, ex if r == 0,1,2,3,4 etc... is there any way I can do this more efficiently?
Some clarifications: const int n decides the size of the matrix (n x 3), const int r decides what row is negated (0 <= r < n).
A second loop will help. I generally find pointer code a bit harder to read. Particularly with Matrix manipulation you might be better off using array syntax instead of pointer syntax.
for (int y = 0; y < 3; y++)
{
for (int x = 0; x < 3; x++)
{
printf("%d ", *(a + 3 * (r + x) + y));
}
printf("\n");
}
Particular case (3 rows):
int mul = 1, y = 0;
for (int x = 0; x < n; x++) {
mul = x == r ? -1 : 1;
y = (a + 3 * x);
printf("%d ", (*y) * mul);
printf("%d ", (*y + 1) * mul);
printf("%d ", (*y + 2) * mul);
printf("\n");
}
More generic (m rows):
int mul = 1;
for (int x = 0; x < n; x++) {
mul = x == r ? -1 : 1;
for (int y = 0; y < m; y++) {
printf("%d ", ((*(a + m * x + y)) * mul);
}
printf("\n");
}
Note: In new compilers there is also no difference in speed between array or pointer syntax.
You could write a function that accepts a one-dimensional array (a row of your matrix) and then using this function you could in a loop output its all rows or output a selected row.
Here is a demonstrative program.
#include <stdio.h>
void negate_row( const int *a, size_t n, int width )
{
if ( width < 1 ) width = 1;
for ( const int *p = a; p != a + n; ++p )
{
printf( "%*d ", width, -*p );
}
putchar( '\n' );
}
int main(void)
{
enum { M = 3, N = 4 };
int matrix[M][N] =
{
{ 0, 1, 2, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
for ( int ( *p )[N] = matrix; p != matrix + M; ++p )
{
negate_row( *p, N, 3 );
}
return 0;
}
The program output is
0 -1 -2 -4
-5 -6 -7 -8
-9 -10 -11 -12
As you showed a code where you are using pointers tp output elements of an array then in this demonstrative program I am also using pointers everywhere to access elements of an array.
The third parameter of the function specifies the width of the field for an outputted value.
To output the matrix in the reversed order of rows you can use the loop shown in the program blow.
#include <stdio.h>
void negate_row( const int *a, size_t n, int width )
{
if ( width < 1 ) width = 1;
for ( const int *p = a; p != a + n; ++p )
{
printf( "%*d ", width, -*p );
}
putchar( '\n' );
}
int main(void)
{
enum { M = 3, N = 4 };
int matrix[M][N] =
{
{ 0, 1, 2, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
for ( int ( *p )[N] = matrix + M; p != matrix; )
{
negate_row( *--p, N, 3 );
}
return 0;
}
The program output is
-9 -10 -11 -12
-5 -6 -7 -8
0 -1 -2 -4
You can generalize the function easily: as long as the row is within the matrix, your code works for any row. Also note that it is better to use a separate function to print the matrix.
#include <stdio.h>
void negate_row(const int n, const int r, int *a) {
if (r >= 0 && r < n) {
// negate row r
for (int col = 0; col < 3; col++) {
*(a + 3 * r + col) *= -1;
}
}
}
void print_matrix(const int n, int *a, const char *title) {
if (title) {
printf("%s:\n", title);
}
for (int row = 0; row < n; row++) {
for (int col = 0; col < 3; col++) {
printf("%d ", *(a + 3 * row + col));
}
printf("\n");
}
printf("\n");
}
int main() {
int matrix[5 * 3] = {
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
};
print_matrix(5, matrix, "Matrix");
negate_row(5, 0, matrix);
print_matrix(5, matrix, "Matrix with negated row");
negate_row(5, 3, matrix);
print_matrix(5, matrix, "Matrix with two negated rows");
negate_row(5, 0, matrix);
negate_row(5, 3, matrix);
print_matrix(5, matrix, "Matrix back to origin");
return 0;
}
Output:
Matrix:
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14
Matrix with negated row:
0 -1 -2
3 4 5
6 7 8
9 10 11
12 13 14
Matrix with two negated rows:
0 -1 -2
3 4 5
6 7 8
-9 -10 -11
12 13 14
Matrix back to origin:
0 1 2
3 4 5
6 7 8
9 10 11
12 13 14

Create sparse matrix that stores only the row and column indices of a matrix using C

I have a (2 x 4) binary matrix A and I want to replace this matrix by a (2*scale x 4*scale) binary matrix B such that element 1 in matrix A is replaced by (scale x scale) identity matrix and element 0 is replaced by (scale x scale) zero matrix.
matrix A:
1 0 1 0
0 1 0 0
matrix B:
1 0 0 0 1 0 0 0
0 1 0 0 0 1 0 0
0 0 1 0 0 0 0 0
0 0 0 1 0 0 0 0
However I need only the position of 1's in the matrix B, therefore I create a sparse matrix that stores only the row and column indices of matrix B.
0, 0
0, 4
1, 1
1, 5
2, 2
3, 3
I am doing this in 2 steps for the below sample code : (1) create matrix B (2) create sparse structure.
This is a sample code where the macros defined is just for this example, in general I work with huge matrices of order 10000 x 10000 or more.
I want to avoid step 1 (i.e creation of matrix B) and directly create the sparse structure to store the row and column indices. Could someone please assist me with this?
#include <stdio.h>
#define rowSize 2 //!< row size of matrixA
#define colSize 4 //!< column size of matrixA
#define scalingFactor 2 //!< scaling factor to increase the size of matrixA
#define nonZeros 3 //!< number of 1's in matrixA
//!< struct to hold the position of 1's in matrixB
typedef struct sparseMatrix{
int row;
int col;
}sparseMatrix;
int main()
{
int row, col, idx;
int matrixA[rowSize][colSize] = {{1,0,1,0},{0,1,0,0}};
int matrixB[rowSize*scalingFactor][colSize*scalingFactor] = {{0}};
sparseMatrix matrixC[nonZeros*scalingFactor];
// check for the element 1 in matrixA and replace it with an identity matrix of size 'scalingFactor'
for(row = 0; row < rowSize; row++){
for(col = 0; col < colSize; col++){
if(matrixA[row][col] == 1){
for (idx = 0; idx < scalingFactor; idx++){
matrixB[(scalingFactor) * row + idx][(scalingFactor) * col + idx ] = 1; // matrixB created
}
}
}
}
// create a sparse matrix that stores only position of 1's in matrixB
idx = 0;
for(row = 0; row < rowSize*scalingFactor; row++){
for(col = 0; col < colSize*scalingFactor; col++){
if(matrixB[row][col] == 1){
matrixC[idx].row = row;
matrixC[idx].col = col;
idx++;
}
}
}
// print the sparse matrix
for(idx = 0; idx < nonZeros*scalingFactor; idx++){
printf("%d, %d\n",matrixC[idx].row, matrixC[idx].col);
}
return 0;
}
I believe you could integrate your second for loop inside the first. Therefore, instead of creating the matrix B you would directly save its indexes:
int i = 0; // variable to save matrixC current index
// check for the element 1 in matrixA and replace it with an identity matrix of size 'scalingFactor'
for (row = 0; row < rowSize; row++) {
for (idx = 0; idx < scalingFactor; idx++) {
for (col = 0; col < colSize; col++) {
if (matrixA[row][col] == 1) {
// instead of creating a temporary dense matrix,
// just save its indexes:
matrixD[i].row = row * scalingFactor + idx;
matrixD[i].col = col * scalingFactor + idx;
i++;
}
}
}
}

Swap columns using pointers in C

I am really stucked on this problem, my C code has worked very well using multidimensional arrays but i need to do the same using pointers but i'll describe the problem first.
Having the following matrix, i will get a number which will be the number of permutations (the number of swapping of columns that will move to the right and the last column will move to the first column).
For example
The number of column's permutations: 5
| 1 2 3 | -----> | 2 3 1 |
| 3 1 2 | -----> | 1 2 3 |
| 2 3 1 | -----> | 3 1 2 |
I wrote the following code using pointers, as you can see i build the matrix with multidimensional array and assign all of it into a pointer:
short elementMatrix[3][3] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short *element_matrix;
element_matrix = *elementMatrix;
int counter = 1;
while (counter <= 5)
{
for (int i = 0; i < 3; i++)
{
int temp = elementMatrix[i][PR.elem_mat_size - 1];
*outElementMatrix = *outElementMatrix + i * PR.elem_mat_size + PR.elem_mat_size - 1;
for (int j = 3 - 1; j >= 0; j--)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *(outElementMatrix + i * PR.elem_mat_size + j - 1);
if (j == 0)
{
*(outElementMatrix + i * PR.elem_mat_size + j) = *outElementMatrix;
}
}
}
counter++;
}
Since you want to swap out columns, it makes sense to have the pointers represent the columns. That way, you can swap a pointer to swap a column. So let's have an array of 3 pointers to a column.
short* col[3];
Each column consists of 3 shorts, so allocate that much memory.
for (int i = 0; i < 3; i++) {
col[i] = (short*)malloc(3 * sizeof(short));
}
Now to initialize the Matrix. This is a bit verbose, so if anyone knows a better way, edit away. :)
col[0][0] = 1; col[1][0] = 2; col[2][0] = 3;
col[0][1] = 3; col[1][1] = 1; col[2][1] = 2;
col[0][2] = 2; col[1][2] = 3; col[2][2] = 1;
Now we do the swap. Note how you need a temp variable, like Rishikesh Raje suggested. Also note that three swaps bring it back to the original, so instead of swapping n times, you only have to swap n % 3 times. Of course it's going to be pretty much instant with 5 or 2 swaps, but if you have to do like a billion, the difference should be noticeable.
for (int i = 0; i < 5; i++) {
short* temp = col[2];
col[2] = col[1];
col[1] = col[0];
col[0] = temp;
}
We assure that the result is correct by printing it:
for (int i = 0; i < 3; i++) {
printf("%d %d %d\n", col[0][i], col[1][i], col[2][i]);
}
You can consider the permutations as a rotation of each row in the matrix and, unless you have to somehow use the matrix after each step, calculate only the final result.
I'll use an extra buffer to help with the swaps.
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
// rotate the values of an array using a buffer to ease the swappings
void rotate_(size_t n, void *arr, void *tmp, size_t offset)
{
assert(n && arr && tmp && offset <= n);
// casting to perform pointer arithmetic
memcpy(tmp, (char *)arr + (n - offset), offset);
memmove((char *)arr + offset, arr, n - offset);
memcpy(arr, tmp, offset);
}
void rotate_columns_short(size_t r, size_t c, short mat[r][c], short *buf, int n)
{
// clamp the value of the offset to the number of columns
size_t offset = (n >= 0
? n % c
: c - -n % c) * sizeof(short);
// transform each row
for (short *row = &mat[0][0], *row_end = row + r * c;
row != row_end;
row += c)
{
rotate_(c * sizeof(short), row, buf, offset);
}
}
void print_matrix_short(size_t r, size_t c, short mat[r][c])
{
for (size_t i = 0; i < r; ++i)
{
for (size_t j = 0; j < c; ++j)
{
printf(" %hd", mat[i][j]);
}
puts("");
}
}
#define ROWS 3
#define COLS 3
int main(void)
{
short matrix[ROWS][COLS] = {{1, 2, 3},
{3, 1, 2},
{2, 3, 1}};
short buf[COLS];
print_matrix_short(ROWS, COLS, matrix);
puts("");
rotate_columns_short(ROWS, COLS, matrix, buf, 5);
print_matrix_short(ROWS, COLS, matrix);
}
The output beeing:
1 2 3
3 1 2
2 3 1
2 3 1
1 2 3
3 1 2

Function to left shift a 2D array in C

I'm writing a function within my program to left shift all the numbers in an array that was passed to the function. An example is:
1 2 3
4 5 6
becomes
2 3 4
5 6 1
My code is:
void LeftShift(int array[][N])/*Get the array from main*/
{
int r, c, temp;
for(r = 0; r < M; r++) { //Start at row 0 and add one each time
for(c = 0; c < N; c++) { //Start at column 0 and add one each time
if(c > 0) {
array[r][c] = array[r][c-1]; //Number is moved over one if its not the first column
}
else if(c == 0 && r > 0) { //If its first column but not first row
array[r][c] = array[r-1][N-1];//Move number up one row and too last column
}
else {
temp = array[r][c];//If its first column and first row store value in temp
}
}
}
array[M-1][N-1] = temp;//Put temp value at end of array
}
When I print this out all I get is the first number from the original array in every spot in the array. M is defined at the top to be 6 and N is defined to be 5. After this runs, I call a function that prints out the new array and all I get is the first value 30 times in an array.
2-D arrays are contiguous in memory, so you can iterate over it as if it were a 1-D array:
void left_rotate(int array[][N])
{
int *flat = (int *)array;
int temp = flat[0];
for ( size_t i = 1; i < M*N; ++i )
flat[i-1] = flat[i];
flat[M*N-1] = temp;
}
The for loop could also be replaced with a single block move:
memmove(&flat[0], &flat[1], (M*N-1) * sizeof *flat);
array[r][c] = array[r][c-1];
should be
array[r][c-1] = array[r][c];
Likewise for the row shift.
You can go throw the array, having a pointer following the last place you visited, and moving the elements, as in this example:
#define nrows 4
#define ncols 4
int array[nrows][ncols] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int main()
{
int row, col;
int saved_int;
int *p = &saved_int;
/* rotate elements */
for(row = 0; row < nrows; row++)
for (col = 0; col < ncols; col++) {
*p = array[row][col];
p = &array[row][col];
} /* for */
*p = saved_int;
/* print matrix */
for (row = 0; row < nrows; row++) {
for (col = 0; col < ncols; col++)
printf( "%s%d",
(col ? "\t" : ""),
array[row][col]);
printf("\n");
} /* for */
return 0;
} /* main */

Resources