I have a matrix that is represented by a one dimensional array,
example:
the matrix
0 1 2 3
4 5 6 7
8 9 10 11
the array
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
now give the dimensions of this matrix and the array I want to find the transpose, i.e.
0, 4, 8, 1, 5, 9, 2, 6, 10, 3, 7, 11
I'm working in C and here is my code
#include <stdlib.h>
#include <stdio.h>
void transpose(int *array, int m, int n){
int new_array[12];
for (int i=0; i<m*n; i++) {
new_array[i] = ??;
}
for (int i=0; i<m*n; i++) {
array[i] = new_array[i];
}
}
void print_array(int array[], int size){
for (int i=0; i<size; i++) {
printf("%d\n",array[i]);
}
}
int main(){
int array[12];
for (int i=0; i<12; i++) {
array[i]=i;
}
print_array(array,12);
transpose(array,3,4);
print_array(array,12);
return 0;
}
I've tried a dozen times and failed. Is there a simple way to do this that I have missed?
Use couple of for loops to make the code easier to follow.
void transpose(int *array, int m, int n){
int new_array[12];
for (int i = 0; i < m; ++i )
{
for (int j = 0; j < n; ++j )
{
// Index in the original matrix.
int index1 = i*n+j;
// Index in the transpose matrix.
int index2 = j*m+i;
new_array[index2] = array[index1];
}
}
for (int i=0; i<m*n; i++) {
array[i] = new_array[i];
}
}
void transpose(int *array, int m, int n){
int new_array[12];
int k = 0;
for(int i = 0; i < n; i++){
for (int j = 0; j < m; j++){
new_array[k++] = array[j*n + i];
}
}
for (int i=0; i<m*n; i++) {
array[i] = new_array[i];
}
}
Write the transpose in terms of a double loop over range [0..n) and [0..m) and calculate the indexes corresponding to the old position and the new position:
#include <stdio.h>
static void transpose(int *array, int m, int n)
{
int new_array[m * n];
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
int old_idx = i * n + j;
int new_idx = j * m + i;
new_array[new_idx] = array[old_idx];
}
}
for (int i = 0; i < m * n; i++)
{
array[i] = new_array[i];
}
}
static void print_array(int array[], int size)
{
for (int i = 0; i < size; i++)
{
printf(" %d", array[i]);
}
putchar('\n');
}
int main(void)
{
int array[12];
for (int i = 0; i < 12; i++)
{
array[i] = i;
}
print_array(array, 12);
transpose(array, 3, 4);
print_array(array, 12);
return 0;
}
The functions have to be pre-declared or made static to compile with my default compilation options. The transpose() function shown will work with any shape (size) of matrix (whereas the original won't work if the product of the dimensions is more than 12). I flattened the output from the array printer, too (though I'd probably make it print matrix shaped output if it were for 'production' use). I do assume that you have C99, or C11 with VLA support.
$ ./trans
0 1 2 3 4 5 6 7 8 9 10 11
0 4 8 1 5 9 2 6 10 3 7 11
$
I have changed:
for (int i = 0 ; i < m*n ; i++) {
new_array[i] = ??;
}
to:
int ctr = 0;
for (int i = 0 ; i <= m*n ; i++) {
if (ctr > m*n)
ctr -= m*n - 1;
new_array[i] = array[ctr];
ctr += n;
}
The logic is quite simple. Each row is n integers long and so the number below a num in the 2-D matrix form would be n+num
You can rewrite your transpose function as like this:
static void transpose(int *array, int m, int n)
{
int *temp=malloc(m*n*sizeof(int)); //need to create a temporary array.
memcpy(temp,array,m*n*sizeof(int));
int i, j;
for (i = 0; i < m; ++i)
{
for (j = 0; j < n; ++j)
{
array[j*m+i]=temp[i*n+j];
}
}
free(temp);
}
You almost had it, I think this would do it...
void transpose(int *array, int m, int n){
int new_array[12];
int count;
count = 0;
for (int i=0; i < n; i++) {
for (int j=0; j < m; j += n) {
new_array[count++] = i + j;
}
}
for (int i=0; i < m * n; i++) {
array[i] = new_array[i];
}
}
This algorithm works for any number of rows an columns:
for (std::size_t i = 0; i < col; i++) {
for (std::size_t j = 0; j < row; j++) {
transpose[c++] = array[j * col + i];
}
}
Related
I'm trying to multiply two matrixes in C but the result gives me:
\23 23\
\23 23\
instead of
\23 20\
\55 48\
1x1 of the matrix keeps repeating and it seems like the matResult[i][j]=sum isn't taking in the sum. The number of rows and columns are defined and there are no scans. I also used a function to calculate the multiplication of the matrix so that I could later use it in the main.
#include <stdio.h>
#define M 2 // m is the number of rows
#define N 2 // n is the number of columns
int i;
int j;
int k;
int sum;
/*
Function to calculate the multiplication of 2 matrixes
*/
int multiMat(int mat1[M][N], int mat2[M][N], int matResult[M][N]) {
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
for (int k = 0; k < N; k++) {
sum = sum + (mat1[i][k] * mat2[k][j]);
}
matResult[i][j] = sum;
sum = 0;
}
}
return matResult[i][j];
}
int main(void) {
int mat1[M][N] = {{1, 2}, {3, 4}};
int mat2[M][N] = {{9, 8}, {7, 6}};
int matResult[M][N];
printf("\n\n RESULT ");
printf("\n ===============\n");
for (int i = 0; i < M; i++) {
for (int j = 0; j < N; j++) {
printf(" %d\t", multiMat(mat1, mat2, matResult));
}
printf("\n");
}
return 0;
}
Here's my version of your code cleaned up. I've removed M as your matrices are square and your code won't easily adapt to multiplying two non-square matrices (though, as I noted in a comment, you can multiply an M×N matrix by an N×P matrix, and the result is an M×P matrix).
#include <stdio.h>
#define N 2 // n is the size of the square matrices
static void multiMat(int mat1[N][N], int mat2[N][N], int matResult[N][N])
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
int sum = 0;
for (int k = 0; k < N; k++)
{
sum = sum + (mat1[i][k] * mat2[k][j]);
}
matResult[i][j] = sum;
}
}
}
static void printMat(const char *tag, int mat[N][N])
{
printf("%s (%dx%d):\n", tag, N, N);
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
printf(" %3d", mat[i][j]);
}
printf("\n");
}
}
int main(void)
{
int mat1[N][N] = {{1, 2}, {3, 4}};
int mat2[N][N] = {{9, 8}, {7, 6}};
int mat3[N][N];
multiMat(mat1, mat2, mat3);
printMat("Mat1", mat1);
printMat("Mat2", mat2);
printMat("Mat3", mat3);
return 0;
}
When run, it produces the output:
Mat1 (2x2):
1 2
3 4
Mat2 (2x2):
9 8
7 6
Mat3 (2x2):
23 20
55 48
The result (renamed Mat3 in this code) is what you wanted. It's often a good idea to print the inputs as well as the output — it ensures that the computer is thinking about things the same way you are. It also encourages writing functions like printMat(). It is possible to provide the dimensions of the matrices to the functions using VLA (variable-length array) notation. For example, a more general matrix multiply function might be:
void MatrixMuliply(size_t M, size_t N, size_t P, int mat1[M][N], int mat2[N][P], int mat3[M][P])
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < P; j++)
{
int sum = 0;
for (int k = 0; k < N; k++)
sum += mat1[i][k] * mat2[k][j];
mat3[i][j] = sum;
}
}
}
Here we are given a martix and we have to find out whether the matrix is symmetrix or not. I want to optimise it using array pointer or passsing by reference or you can suggest better approach , which uses multiple concepts, and please provide an explanation , it would be helpful.
I am learning arrays so, that why I am asking you to use multiple concepts , I want to see if there is a better approach
#include <stdio.h>
#include <stdlib.h>
void swap(int arr[3][3], int i, int j)
{
int temp;
temp = arr[i][j];
arr[i][j] = arr[j][i];
arr[j][i] = temp;
}
void check(int arr[3][3], int i, int j)
{
static int count = 0;
if (arr[i][j] == arr[j][i])
{
count++;
if (count == 9)
{
printf("matrix is symmetric");
}
}
}
int main()
{
int arr[3][3] = {1, 3, 3,
3, 1, 5,
3, 5, 5};
int i, j;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
for (int i = 0; i < 3; i++)
{
for (int j = i + 1; j < 3; j++)
{
swap(arr, i, j);
}
printf("\n");
}
printf("THE TRANSPOSE MATRIX IS \n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
check(arr, i, j);
if (arr[i][j] != arr[j][i])
{
printf("matrix is non-symmetric");
exit(0);
}
}
}
}
To find symmetric matrix simply use the following code:
#include <stdio.h>
#define dim 4
int main()
{
int i=0;
int arr[dim][dim]= {1, 3, 2, 3,
3, 1, 5, 4,
2, 5, 5, 16,
3, 4, 16, 7};
int isSymmetric = 1;
while (isSymmetric && i<dim)
{
for (int j = i; j < dim; j++)
{
if(arr[i][j]!=arr[j][i]) {
isSymmetric = 0;
break;
}
}
i++;
}
isSymmetric==1?printf("Symmetric"):printf("notSymmetric");
return 0;
}
The complexity of this algorithm at most is O(N/2) when N is the number of elements.
I have a single dimensional array with the following values:
10010011
I would like to convert this single dimensional array to a 2X4 Matrix with the following order:
1001
0011
The code that I attempted is below:
#include <stdio.h>
#include <stdlib.h>
#define rows_Matrix 2
#define cols_Matrix 4
void print2DArray(unsigned **arr, int m, int q);
int main()
{
int k = 0;
unsigned Array[8] = { 1, 0, 0, 1, 0, 0, 1, 1};
//Allocation of Memory.
unsigned **Matrix = (unsigned **)malloc(sizeof(unsigned *)*rows_Matrix); //Rows
for (int i = 0; i < rows_Matrix; i++) //Rows
{
Matrix[i] = (unsigned *)malloc(sizeof(unsigned ) * cols_Matrix); //Columns
}
do
{
for (int i = 0; i < rows_Matrix; i++)
{
for (int j = 0; j < cols_Matrix; j++)
{
Matrix[i][j] = Array[k];
}
}
k++;
} while (k < 8);
print2DArray(Matrix, 2, 4);
return 0;
}
void print2DArray(unsigned **arr, int m, int q)
{
for (int i = 0; i < m; i++) //Rows
{
for (int j = 0; j < q; j++)//Columns
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n");
}
But the answer that I am getting is:
1 1 1 1
1 1 1 1
I would like to know why the values values are not being assigned correctly. It seems the way I am doing it I am just copying the first element of the single dimensional array.
You have incremented in the wrong place. So Array[k] was indicating the same element.
#include <stdio.h>
#include <stdlib.h>
#define rows_Matrix 2
#define cols_Matrix 4
void print2DArray(unsigned **arr, int m, int q);
int main()
{
int k = 0;
unsigned Array[8] = { 1, 0, 0, 1, 0, 0, 1, 1};
//Allocation of Memory.
unsigned **Matrix = (unsigned **)malloc(sizeof(unsigned *)*rows_Matrix); //Rows
for (int i = 0; i < rows_Matrix; i++) //Rows
{
Matrix[i] = (unsigned *)malloc(sizeof(unsigned ) * cols_Matrix); //Columns
}
do
{
for (int i = 0; i < rows_Matrix; i++)
{
for (int j = 0; j < cols_Matrix; j++)
{
Matrix[i][j] = Array[k];
k++; //updated
}
}
} while (k < 8);
print2DArray(Matrix, 2, 4);
return 0;
}
void print2DArray(unsigned **arr, int m, int q)
{
for (int i = 0; i < m; i++) //Rows
{
for (int j = 0; j < q; j++)//Columns
{
printf("%d\t", arr[i][j]);
}
printf("\n");
}
printf("\n");
}
I have a 2D array called matrix, now I would like to add one to every element.
#include <stdio.h>
#include <stdlib.h>
int **add_one(int **matrix, int m, int n) {
int i, j;
int **new_mat;
new_mat = (int **) malloc(m * n *sizeof(int));
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
new_mat[i][j] = matrix[i][j] + 1;
}
}
//return the 2nd rank pointer
return new_mat;
}
int main() {
int matrix[3][2] = {1, 2, 3, 4, 5, 6};
int **new_mat;
int i, j;
new_mat = add_one(matrix, 3, 2);
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
printf("%d ", new_mat[i][j]);
}
printf("\n");
}
free(new_mat);
}
However, the compiler told me that
[Error] cannot convert 'int (*)[2]' to 'int**' for argument '1' to 'int** add_one(int**, int, int)'
It works a bit differently from what you thought
#include <stdio.h>
#include <stdlib.h>
// you can only pass what you have
int **add_one(int matrix[3][2], int m, int n)
{
int i, j;
int **new_mat;
// allocate m pointers (the rows)
new_mat = malloc(m * sizeof(*new_mat));
for (i = 0; i < m; i++) {
// allocate space for n ints
new_mat[i] = malloc(n * sizeof(int));
for (j = 0; j < n; j++) {
new_mat[i][j] = matrix[i][j] + 1;
}
}
//return the 2nd rank pointer
return new_mat;
}
int main()
{
// you forgot to encapsulate the rows, too
int matrix[3][2] = { {1, 2}, {3, 4}, {5, 6} };
int **new_mat;
int i, j;
new_mat = add_one(matrix, 3, 2);
for (i = 0; i < 3; i++) {
for (j = 0; j < 2; j++) {
printf(" %d ", new_mat[i][j]);
}
printf("\n");
}
free(new_mat);
}
If you want to pass the two-star matrix as a two-star matrix you need to build it like the new_mat in the function add_one.
Im asking for help once again. This time I found myself in the midst of a task which I found on the internet and I cant find a good solution. At first I thought of bubble sort, but I didnt seem to find a way to use it with multidimensional array.
The task asks to find 3 smallest elements which arent repeating on the second array.
So far my code looks like this, though Ive removed a lot of it... Since it was a very wrong and futile aproach.
Everything was written in C.
Thanks for the help.
3
1 2 3
3 3 3
3 3 3
5 4 6
6 4 5
4 5 6
This is the given information for the file
#include stdio.h
#include stdlib.h
int main()
{
FILE *fptr;
fptr = fopen("Duomenys.txt", "r");
int i, j;
int k, l;
int bubbleTmp;
fscanf(fptr, "%d ", &k);
l = k;
int a[k][k];
int b[k][k];
for(i = 0; i < k; i++)
{
for(j = 0; j < l; j++)
{
fscanf(fptr,"%d ",&a[i][j]);
printf("%d ", a[i][j]);
}
printf("\n");
}
printf("\n\n\n");
for(i = 0; i < k; i++)
{
for(j = 0; j < l; j++)
{
fscanf(fptr,"%d ",&b[i][j]);
printf("%d ", b[i][j]);
}
printf("\n");
}
// Bubble Sort
for(i = 0; i < k; i++)
{
for(j = 0; j < l; j++)
{
if(a[i][j] > a[i][j+1])
{
}
}
}
fclose(fptr);
return 0;
}
To find the minimum and its position in the array:
int min = a[0][0], i_min = 0, j_min = 0;
for(i = 0; i < k; i++)
{
for(j = 0; j < l; j++)
{
if(a[i][j] < min)
{
min = a[i][j];
i_min = i;
j_min = j;
}
}
}
After the first try, you repeat it two more times, avoiding the minimums alrerady found. The positions of each minimums are known.
Previously, it was a suggestion.
Now, here is the solution:
//----------------------------------------------------------------------------
#include <iostream>
#include <iomanip>
#include <ctime>
//----------------------------------------------------------------------------
int **CreateArray (int N, int M)
{
int **arr = new int*[N];
for (int i = 0; i<N; i++)
arr[i] = new int [M];
for (int i = 0; i<N; i++)
for (int j = 0; j<M; j++)
arr[i][j] = rand()%10 - rand()%10;
return arr;
}
void DestroyArray (int **arr, int N)
{
for (int i = 0; i<N; i++)
delete [] arr[i];
delete [] arr;
}
void PrintArray (int **arr, int N, int M)
{
for (int i = 0; i<N; i++)
{
for (int j = 0; j<M; j++)
std::cout << std::setw(7) << arr[i][j];
std::cout << "\n";
}
std::cout << "\n";
}
//----------------------------------------------------------------------------
typedef struct _min
{
int value;
int i;
int j;
} TMin;
//---------------------------------------------------------------------------
void FindMin (int **arr, int N, int M, TMin **mins, int min_count)
{
mins[min_count]->value = arr[0][0];
mins[min_count]->i = 0;
mins[min_count]->j = 0;
for (int i = 0; i<N; i++)
for (int j = 0; j<M; j++)
{
if (arr[i][j] < mins[min_count]->value)
{
bool prev = false;
for (int k = 0; k<min_count; k++)
if (i == mins[k]->i && j == mins[k]->j)
{
prev = true;
break;
}
if (!prev)
{
mins[min_count]->value = arr[i][j];
mins[min_count]->i = i;
mins[min_count]->j = j;
}
}
}
}
//----------------------------------------------------------------------------
int main()
{
//array creation, filling, printing
srand ((unsigned int)time (NULL));
int N = 6, M = 7;
int **arr = CreateArray (N, M);
PrintArray (arr, N, M);
//container for 3 minimums
TMin **mins = new TMin*[3];
for (int i = 0; i<3; i++)
mins[i] = new TMin;
//let us find them
int min_count = -1;
while (++min_count < 3)
FindMin (arr, N, M, mins, min_count);
//result
for (int i = 0; i<3; i++)
std::cout << "arr[" << mins[i]->i << "][" <<mins[i]->j << "] = " << mins[i]->value << "\n";
//cleaning memory
for (int i = 0; i<3; i++)
delete [] mins[i];
delete [] mins;
DestroyArray (arr, N);
std::cin.sync();
std::cin.get();
return 0;
}
//-----------------------------------------------------------------------------