C function to transpose matrix does not update matrix - c

I am currently building a matrix calculator (required to make with pointers) as part of my introductory C assignment, and I am currently trying to make an option to Transpose a 3x3 matrix (swapping the rows of a matrix with it's columns).
However, when I apply the function on the matrix nothing happens to it.
Here is the code for the transposition function.
void transposeMatrix(int matrix[3][3]) {
int row;
int col;
int temp = 0;
for (row = 0; row<3; row++) {
for (col = 0; col < 3; col++) {
temp = *(*(matrix+row)+col);
*(*(matrix+row)+col) = *(*(matrix+col)+row);
*(*(matrix+col)+row) = temp;
}
}
}
It is just a standard swapping algorithm with a temp variable.
Here is the code for the printing function
void printMatrix(char *desc,int matrix[3][3]) {
int row;
int column;
printf("matriks %s:\n",desc);
for (row = 0; row < 3; row++) {
for (column = 0; column < 3; column++) {
printf(" %d", matrix[row][column]);
}
printf("\n");
}
}
And here is how I call the function:
int sampleM1[3][3] = {{2,2,4}, {1,1,1}, {1,1,1}};
printMatrix("before transposition", sampleM1);
transposeMatrix(sampleM1);
printMatrix("after transposition" , sampleM1);
The output of the entire operation is that sampleM1 does not change at all. Is there any way to fix this problem?

As #TomKarzes noted above you visit the same index of the matrix twice, and avoid that by starting the inner loop at row + 1. You mentioned that you needed to use pointer syntax, which is fine of course, but swap() now localizes the ugliness (to arguments) for you to change as you see fit.
#include <stdint.h>
#include <stdio.h>
#define N 3
void swap(int *a, int *b) {
int tmp = *a;
*a = *b;
*b = tmp;
}
void printMatrix(int matrix[N][N]) {
for (uint8_t row = 0; row < N; row++)
for (uint8_t col = 0; col < N; col++)
printf("%d%s", matrix[row][col], col + 1 < N ? ", " : "\n");
}
void transposeMatrix(int matrix[N][N]) {
for (uint8_t row = 0; row < N; row++)
for (uint8_t col = row + 1; col < N; col++)
swap(&matrix[row][col], &matrix[col][row]);
}
int main() {
int matrix[N][N] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
printMatrix(matrix);
transposeMatrix(matrix);
printMatrix(matrix);
}
Here is the output of the above:
1, 2, 3
4, 5, 6
7, 8, 9
1, 4, 7
2, 5, 8
3, 6, 9

Related

Circular permutation in C

Given a array x with n integer components, write functions that allow performing the following operation: Carry out the circular permutation of the given array
I tried to do without poiters for the code, as it ends up with only arrays
I think the problem is that the array in the pcircular is lost and can't pass the value to the write function
Note: for array > 6 it will not work
#include <stdio.h>
int ArraySize(){ // get the size of the array
int size;
printf("What's the array size? ");
scanf("%d", &size);
return size;
}
void readArray(int size, int array[]){ /*put the values ​​in the first array*/
for (int i = 0; i < size; i++){
printf("What is the \033[1;36m%d\033[m value? ", i+1);
scanf("%d", &array[i]);
}
}
void pcircular(int size, int array[size][size]){ //Circular permutation function
for (int j = 0; j <= size; j++){
/* printf("("); */
for (int i = 0; i < size; i++){
if (i == size - 1){
array[j+1][0] = array[j][i];
/* printf("%d", array[j+1][0]); */
}
else{
array[j+1][i+1] = array[j][i];
/* printf("%d", array[j+1][i+1]);
printf(", "); */
}
}
/* printf(")"); */
}
}
void writeArray(int size, int array[size][size]){ //Write the Array
for (int i = 0; i <= size; i++){
printf("(");
for (int j = 0; j < size; j++){
/* printf("\ni = %d j = %d\n", i, j); */
printf("%d", array[i][j]);
if (j != size-1){
printf(", ");
}
}
printf(")");
}
}
void main(){
int size = ArraySize();
int list[size][size]; // create the array
readArray(size, list[0]);
pcircular(size, list);
writeArray(size, list);
}
Input:
What's the array size? 6
What is the 1 value? 1
What is the 2 value? 2
What is the 3 value? 3
What is the 4 value? 4
What is the 5 value? 5
What is the 6 value? 6
Expected Output:
(1, 2, 3, 4, 5, 6)(6, 1, 2, 3, 4, 5)(5, 6, 1, 2, 3, 4)(4, 5, 6, 1, 2, 3)(3, 4, 5, 6, 1, 2)(2, 3, 4, 5, 6, 1)(1, 2, 3, 4, 5, 6)
Real Output:
(
write your pcircular function as follow:
void pcircular(int size, int array[size][size]){ //Circular permutation
for (int j = 1; j <= size; j++){
for (int i = 0; i < size; i++){
array[j][i ] = array[j - 1][(i + 1) % size];
}
}
}
but the main problem is here:
int list[size + 1][size]; // create the array
since you are creating one more row than the number, indeed the last row is copy of the first row.
if you dont change the pcircular function, and use your version, you should as well add to second dimention too.

Concentric square matrix

I have coding problem to write concentric square matrix (biggest number is in the middle) For example user needs to write an matrix For example:
5 5 5 5 5
5 6 6 6 5
5 6 7 6 5
5 6 6 6 5
5 5 5 5 5
My program has to output "Yes" because this is, by my program's rules, a concentric square matrix.
5 5 5 5 5
5 6 6 6 5
5 6 7 8 5
5 6 6 6 5
5 5 5 5 5
This is not a concentric square matrix because 8 is in 4th column and 3rd row.
This is my code:
#include <stdio.h>
int main() {
int mat[100][100];
int i,j;
int n;
scanf("%d",&n);
printf("Unesite matricu; ");
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&mat[i][j]);
}
}
}
I don't know how to do the rest of it so if someone can help me, I would be happy :))
Comment::
I forgot to say that only odd numbers can be the dimension of the matrix (1,3,11,27). The only final output of the program has to be "YES (if the matrix is a concentric square matrix) or "NO" (if it's not). I know how to make a concentric square matrix when the user inputs a number (for example, 4) and the matrix has 2*n-1 dimensions. And through the loops, the program automatically makes the matrix (if you know what I mean). But for my matrix, the user has to input all the elements of the matrix and the program has to check if the matrix is concentric or not.
Would you please try the following:
#include <stdio.h>
int main() {
int mat[100][100];
int ii[] = {0, 1, 0, -1}; // incremental numbers of i
int jj[] = {1, 0, -1, 0}; // incremental numbers of j
int i, j;
int n;
int u, v, w; // variables to walk on edges
int val; // value of the element
int prev; // previous value in one outer edge
int length; // length of the edge
// read matrix size and values
printf("Enter the number:\n");
scanf("%d", &n);
printf("Enter the matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
scanf("%d", &mat[i][j]);
}
}
// loop on the edges
for (u = 0; u < n / 2; u++) { // from outmost edge to inner
i = u; j = u; // index of the north west corner
val = mat[u][u]; // initial value to compare
for (v = 0; v < 4; v++) { // four sides
length = n - u * 2 - 1; // length of the edge
for (w = 0; w < length; w++) {
i += ii[v]; // one step ahead on the edge
j += jj[v]; // same as above
if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
// if u == 0, skip the comparison with prev
printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
return 1;
}
}
}
prev = mat[i][j];
}
// finally examine the center value (if n is odd number)
if (n % 2) {
if (mat[u][u] <= prev) {
printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
return 1;
}
}
printf("Yes\n");
return 0;
}
The basic concept is to generate a series of indexes of the edge
such as:
[0, 1], [0, 2], [0, 3], [0, 4],
[1, 4], [2, 4], [3, 4], [4, 4],
[4, 3], [4, 2], [4, 1], [4, 0],
[3, 0], [2, 0], [1, 0], [0, 0]
by using the variables i, j and the arrays ii[], jj[].
The example above is the indexes for the outermost edge and go into
the inner edge in the next iteration. Then the values of the index
is compared with the other value in the same edge and the previous
value in the outer edge.
[Edit]
Here is an alternative which does not use an array other than mat[100][100]:
#include <stdio.h>
int main() {
int mat[100][100];
int i, j;
int ii, jj; // incremental values for i and j
int n;
int u, v, w; // variables to walk on edges
int val; // value of the element
int prev; // previous value in one outer edge
int length; // length of the edge
// read matrix size and values
printf("Enter the number:\n");
scanf("%d", &n);
printf("Enter the matrix:\n");
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
scanf("%d", &mat[i][j]);
}
}
// loop on the edges
for (u = 0; u < n / 2; u++) { // from outmost edge to inner
i = u; j = u; // index of the north west corner
val = mat[u][u]; // initial value to compare
for (v = 0; v < 4; v++) { // four sides
ii = (v & 1) * ((v & 1) - (v & 2));
// assigned to {0, 1, 0, -1} in order
jj = ((v + 1) & 1) * (((v + 1) & 1) - ((v + 1) & 2));
// assigned to {1, 0, -1, 0} in order
length = n - u * 2 - 1; // length of the edge
for (w = 0; w < length; w++) {
i += ii; // one step ahead on the edge
j += jj; // same as above
if (mat[i][j] != val || (u > 0 && mat[i][j] <= prev)) {
// if u == 0, skip the comparison with prev
printf("No at [%d][%d] (val=%d)\n", i, j, mat[i][j]);
return 1;
}
}
}
prev = mat[i][j];
}
// finally examine the center value (if n is odd number)
if (n % 2) {
if (mat[u][u] <= prev) {
printf("No at [%d][%d] (val=%d)\n", u, u, mat[u][u]);
return 1;
}
}
printf("Yes\n");
return 0;
}
I created an answer using more functions than just main(). It is more verbose than what is required for your homework — it prints out the matrix it reads and diagnoses the first problem it comes across. It works with both positive and negative numbers, and with matrices with odd or even numbers of elements.
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
enum { MAT_SIZE = 100 };
static int err_error(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
exit(EXIT_FAILURE);
}
static int err_shell(int r, int c, int a_val, int e_val)
{
printf("Element M[%d][%d] = %d vs expected value %d\n", r, c, a_val, e_val);
return 0;
}
static int check_shell(int shell, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
int lb = shell;
int ub = n - shell - 1;
int val = matrix[lb][lb];
/* Check the horizontals */
for (int c = lb; c <= ub; c++)
{
if (matrix[lb][c] != val)
return err_shell(lb, c, matrix[lb][c], val);
if (matrix[ub][c] != val)
return err_shell(ub, c, matrix[ub][c], val);
}
/* Check the verticals */
for (int r = lb; r <= ub; r++)
{
if (matrix[r][lb] != val)
return err_shell(r, lb, matrix[r][lb], val);
if (matrix[r][ub] != val)
return err_shell(r, ub, matrix[r][ub], val);
}
return 1;
}
static int check_matrix(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
for (int i = 0; i <= n / 2; i++)
{
if (check_shell(i, n, matrix) == 0)
return 0;
}
for (int i = 0; i < (n - 1) / 2; i++)
{
if (matrix[i][i] >= matrix[i+1][i+1])
{
printf("Shell %d has value %d but inner shell %d has value %d\n",
i, matrix[i][i], i+1, matrix[i+1][i+1]);
return 0;
}
}
return 1;
}
static int read_size(void)
{
int n;
if (scanf("%d", &n) != 1)
err_error("failed to read an integer\n");
if (n <= 0 || n > MAT_SIZE)
err_error("matrix size %d is not in the range 1..%d\n", n, MAT_SIZE);
return n;
}
static void read_matrix(int n, int matrix[n][n])
{
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (scanf("%d", &matrix[i][j]) != 1)
err_error("failed to read M[%d][%d]\n", i, j);
}
}
}
static int max_field_width(int n, int matrix[MAT_SIZE][MAT_SIZE])
{
int min_val = matrix[0][0];
int max_val = matrix[0][0];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (matrix[i][j] < min_val)
min_val = matrix[i][j];
if (matrix[i][j] > max_val)
max_val = matrix[i][j];
}
}
int fld_width = snprintf(0, 0, "%d", max_val);
if (min_val < 0)
{
int min_width = snprintf(0, 0, "%d", min_val);
if (min_width > fld_width)
fld_width = min_width;
}
return fld_width;
}
static void print_matrix(const char *tag, int n, int matrix[MAT_SIZE][MAT_SIZE])
{
printf("%s (%d):\n", tag, n);
int w = max_field_width(n, matrix) + 1;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%*d", w, matrix[i][j]);
}
putchar('\n');
}
}
int main(void)
{
int matrix[MAT_SIZE][MAT_SIZE];
int n = read_size();
read_matrix(n, matrix);
print_matrix("Input", n, matrix);
if (check_matrix(n, matrix))
printf("YES: Matrix is a valid concentric matrix\n");
else
printf("NO: Matrix is not a valid concentric matrix\n");
return 0;
}
One detail is that this code can be made to use a VLA (variable-length array) by simply replacing MAT_SIZE by n in each function definition and modifying main() to read:
static int check_shell(int shell, int n, int matrix[n][n]) { … }
static int check_matrix(int n, int matrix[n][n]) { … }
static void read_matrix(int n, int matrix[n][n]) { … }
static int max_field_width(int n, int matrix[n][n]) { … }
static void print_matrix(const char *tag, int n, int matrix[n][n]) { … }
int main(void)
{
int n = read_size();
int matrix[n][n];
read_matrix(n, matrix);
print_matrix("Input", n, matrix);
if (check_matrix(n, matrix))
printf("YES: Matrix is a valid concentric matrix\n");
else
printf("NO: Matrix is not a valid concentric matrix\n");
return 0;
}
This reads the matrix size before allocating the matrix, instead of allocating a fixed size matrix first.
The read_size() function enables this change — that input must be done separately from the main matrix scanning code.

Get first col in matrix

I have simple program that gets the sum of main and anti diagonals of a matrix. And then it get the sum of first and last column of a matrix.For example:
1 2 3
4 5 6 --> The matrix
7 8 9
md = 1 + 5 + 9 = 15
ad = 7 + 5 + 3 = 15
lastCol = 3 + 6 + 9 = 18
firstCol = 1 + 4 + 7 = 12
How can i get the sum of the firstCol of a square matrix ? Here is my code:
int main(){
int n;
scanf("%d",&n);
int i,j,a[n][n],firstCol=0,lastCol=0,md=0,ad=0;
for(i = 0;i <n;i++){
for(j=0;j<n;j++){
scanf("%d",&a[i][j]);
}
}
for(i = 0;i <n;i++){
for(j=0;j<n;j++){
if(i==j){
md+=a[i][j];
}
if(i+j==n-1){
ad+=a[i][j];
}
}
}
for(i=0;i<n;i++){
lastCol+=a[i][n-1];
}
}
for (i = 0; i < n; i ++) {
firstCol += a[i][0];
}
Use functions. Try to make them a bit more universal. This one will return sum of the first column of any size array.
long long int sumFirstCol(size_t rows, size_t cols, int (*array)[cols])
{
long long int result = 0;
if(array && rows && cols)
{
for(size_t row = 0; row < rows; row++)
{
result += array[row][0];
}
}
return result;
}
int main(void)
{
int matrix[3][3] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9},};
printf("%lld\n", sumFirstCol(3, 3, matrix));
}

How to transpose a 2 dimensional array on C via call by reference?

As the title says, I am trying to transpose a 2 dimensional matrix by calling by reference.
I have attached my code below. When I run the code, the 2 dimensional array is unchanged.
#include <stdio.h>
#define SIZE 4
void transpose2D(int ar[][SIZE], int rowSize, int colSize);
int main()
{
int testArr[4][4] = {
{1, 2, 3, 4},
{5, 1, 2, 2},
{6, 3, 4, 4},
{7, 5, 6, 7},
};
transpose2D(testArr, 4, 4);
// print out new array
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
printf("%d ", testArr[i][j]);
}
printf("\n");
}
return 0;
}
void transpose2D(int ar[][SIZE], int rowSize, int colSize)
{
for (int i = 0; i < rowSize; i++)
{
for (int j = 0; j < colSize; j++)
{
int temp = *(*(ar + i) + j);
*(*(ar + i) + j) = *(*(ar + j) + i);
*(*(ar + j) + i) = temp;
}
}
}
Have been stuck for a couple of hours, any help is greatly appreciated, thank you!
To fix your function I suggest:
switch element only once, the previous version swapped elements for i=a, j=b and i=b,j=a, so the matrix remained unchanged
use a common a[i][j] syntax
let the non-square matrix be embedded into a larger matrix whose inner dimensions is set to stride.
using VLAs to make the interface a bit more generic
void transpose2D(size_t rows, size_t cols, size_t stride, int ar[][stride]) {
assert(rows <= stride);
assert(cols <= stride);
for (size_t i = 0; i < rows; i++) {
for (size_t j = i + 1; j < cols; j++) {
int tmp = ar[j][i];
ar[j][i] = ar[i][j];
ar[i][j] = tmp;
}
}
}
Exemplary usage:
int testArr[4][4] = {
{1, 2},
{5, 1},
{6, 3},
};
transpose2D(3, 2, 4, testArr);
The algorithm is still very inefficient due to terrible cache miss rates on access to a[j][i]. It can be fixes by tiling and transposing smaller 8x8 blocks, but it is a topic for another day.

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