Im trying to sort a matrix by the sum of its row's digits, from highest to lowest. I dont know if i explained that correctly so here's some photos explaining it.
This is what my code outputs. Basically, it asks you for m and n, which are the dimensions of the matrix. In this example it's a 3x4, 3 rows and 4 columns. Then, the matrix should be sorted by rows, by the sum of row's digits. Which means, instead of what's being outputted in the picture above, the correct result should be this:
I have no idea how to sort this from highest to lowest, i have been trying for hours to no avail.
Here's my code:
#include <stdio.h>
#define N 30
void main(){
double a[N][N], s[N], p;
int i, j, m, n, max;
while(1){
printf("\nm, n? ");
scanf("%d%d", &m, &n);
if(m <= 0 || m > N || n <=0 || n > N)
break;
for(i = 0; i < m; i++){
printf("%2d. row? ", i+1);
for(j = 0; j < n; scanf("%lf", &a[i][j++]));
}
for(i = 0; i < m; i++)
for(s[i] = j = 0; j < n; s[i] += a[i][j++]);
for(j = 0; j < n - 1; j++){
for(max = i, j = i+1; j < n; j++)
if(s[j] > s[max])
max = i;
if(max != j){
p = s[j];
s[j] = s[max];
s[max] = p;
for(j = 0; j < m; j++){
p = a[j][i];
a[j][i] = a[j][max];
a[j][max] = p;
}
}
}
printf("New matrix: \n");
for(i = 0; i < m; i++){
for(j = 0; j < n; printf("%8.2lf", a[i][j++]));
printf("\n");
}
for(j = 0; j < m; j++)
printf("-------------");
printf("\n");
for(j = 0; j < m; printf("%8.2f \n", s[j++]));
printf("\n");
}
}
You can sort the rows of the matrix from highest to lowest, using a simple bubble sort algorithm.Your code modified below:
int main() {
double a[N][N], s[N], p;
int i, j, m, n, max;
while (1) {
printf("\nm, n? ");
scanf("%d%d", & m, & n);
if (m <= 0 || m > N || n <= 0 || n > N)
break;
for (i = 0; i < m; i++) {
printf("%2d. row? ", i + 1);
for (j = 0; j < n; scanf("%lf", & a[i][j++]));
}
for (i = 0; i < m; i++)
for (s[i] = j = 0; j < n; s[i] += a[i][j++]);
for (i = 0; i < m - 1; i++) { // modified here
for (j = i + 1; j < m; j++) { // modified here
if (s[j] > s[i]) { // modified here
p = s[i];
s[i] = s[j];
s[j] = p;
for (int k = 0; k < n; k++) {
p = a[i][k];
a[i][k] = a[j][k];
a[j][k] = p;
}
}
}
}
printf("New matrix: \n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; printf("%8.2lf", a[i][j++]));
printf("\n");
}
for (j = 0; j < m; j++)
printf("-------------");
printf("\n");
for (j = 0; j < m; printf("%8.2f \n", s[j++]));
printf("\n");
}
return 0;
}
Here's how i modified your code to achieve that:
Initialize a loop variable i to 0.
In the outer loop, run the inner loop j from i+1 to m-1.
In the inner loop, compare the sum of the row i with the sum of row
j. If the sum of row j is greater than the sum of row i, swap the
rows using a temporary variable.
After the inner loop finishes, increment the value of i by 1. Repeat
the outer loop until i becomes equal to m-1.
Output:
You can just use qsort to let it handle the sorting and item swapping. Then you only need to write the code for comparing two rows with each other.
Given something like this:
int matrix[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,1,2,3},
};
You'd call qsort as:
qsort(matrix, 3, sizeof(int[4]), compare);
The only complexity is implementing the comparison callback function. There's two things to consider there:
We've told qsort that we have an array of 3 items, each of type int[4]. So the void pointers it passes along to us will actually be pointers to type int[4]. That is: int(*)[4].
qsort sorts in ascending order by default, where the item considered "less" ends up first. So we need to tweak that to get the largest item first.
Example:
int compare (const void* obj1, const void* obj2)
{
const int (*ptr1)[4] = obj1;
const int (*ptr2)[4] = obj2;
size_t sum1=0;
size_t sum2=0;
for(size_t i=0; i<4; i++)
{
sum1 += (*ptr1)[i];
sum2 += (*ptr2)[i];
}
if(sum1 > sum2) // largest sum considered "less" for qsort
return -1;
else
return 1;
return 0;
}
sum1 < sum2 would have placed the smallest row first.
Full example:
#include <stdio.h>
#include <stdlib.h>
int compare (const void* obj1, const void* obj2)
{
const int (*ptr1)[4] = obj1;
const int (*ptr2)[4] = obj2;
size_t sum1=0;
size_t sum2=0;
for(size_t i=0; i<4; i++)
{
sum1 += (*ptr1)[i];
sum2 += (*ptr2)[i];
}
if(sum1 > sum2) // largest sum considered "less" for qsort
return -1;
else
return 1;
return 0;
}
void print_matrix(size_t col, size_t row, int matrix[col][row])
{
for(size_t i=0; i<col; i++)
{
for(size_t j=0; j<row; j++)
{
printf("%d,", matrix[i][j]);
}
puts("");
}
}
int main (void)
{
int matrix[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,1,2,3},
};
print_matrix(3,4,matrix);
puts("");
qsort(matrix, 3, sizeof(int[4]), compare);
print_matrix(3,4,matrix);
}
Related
I need to multiply two square matrixes A and B 15x15.
Unfortunately, I'm getting this kind of error.
I know the problem is in pointers while calculating matrix C.
C[i][j] += *(A + k) * *(B + k)
I hope you can explain me what's wrong. I'm a beginner xD.
Thank you in advance.
#include <stdio.h>
#define N 15
#define _CRT_SECURE_NO_WARNINGS
int main() {
int A[N][N];
int B[N][N];
int C[N][N];
printf("Input matrix A.\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("Enter your element:\n");
scanf_s("%d", &A[i][j]);
}
printf("\n");
}
printf("Input matrix B.\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("Enter your element:\n");
scanf_s("%d", &B[i][j]);
}
printf("\n");
}
printf("Matrix A.\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d\t", A[i][j]);
}
printf("\n");
}
printf("Matrix B.\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d\t", B[i][j]);
}
printf("\n");
}
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
C[i][j] = 0;
for (int k = 0; k < 14; k++) {
C[i][j] += *(A + k) * *(B + k);
k++;
}
}
}
printf("Your result:\n");
printf("Matrix C.\n");
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d\t", C[i][j]);
}
printf("\n");
}
return 0;
}
The problem in the multiplication is that A+k and B+k have type int (*)[15] which means dereferencing it once only makes a pointer out of them; furthermore, you need to take row and column items individually, which means A[i][k] and B[k][j], right? (also, there's no point on using confusing syntax, as the underlying operation is exactly the same).
Here's a fixed and improved version:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define N 15
/* Improvement 1 (type abstraction) */
typedef int NxN_int_matrix[N][N];
/* Improvement 2 (input function & wrapper) */
#define input_matrix(var) input_matrix_ex((var), #var)
static void input_matrix_ex(NxN_int_matrix dst, char *name)
{
printf("Input matrix %s.\n", name);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
/* Improvement 3 (nicer prompt) */
printf("%s[%2d][%2d]: ", name, i, j);
fflush(stdout);
scanf_s("%d", &dst[i][j]);
}
}
printf("\n");
}
/* Improvement 4 (print function) */
#define print_matrix(var) print_matrix_ex(#var, (var))
static void print_matrix_ex(char *name, NxN_int_matrix M)
{
printf("Matrix %s.\n", name);
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
printf("%d\t", M[i][j]);
}
printf("\n");
}
}
/* Improvement 5 (move multiplication to a function too, and fix it) */
static void mult_matrix(NxN_int_matrix dst, NxN_int_matrix a, NxN_int_matrix b)
{
for (int i = 0; i < N; i++) {
for (int j = 0; j < N; j++) {
/* Improvement 6 (don't write out intermediate values) */
int tmp = 0;
for (int k = 0; k < N; k++)
tmp += a[i][k] * b[k][j];
dst[i][j] = tmp;
}
}
}
int main()
{
NxN_int_matrix A, B, C;
input_matrix(A);
input_matrix(B);
print_matrix(A);
print_matrix(B);
mult_matrix(C, A, B);
printf("Your result:\n");
print_matrix(C);
return 0;
}
/* Possible further improvements:
* - using a transposed B might make multiplication faster
*/
I'm trying to write a programm that solves system of equations Ax=B using Gauss-Jacobi iteration method.
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
int main(void) {
double **a, *b, *x, *f, eps = 1.e-2, c;
int n = 3, m = 3, i, j, bool = 1, d = 3;
/* printf("n=") ; scanf("%d", &n);
printf("m=") ; scanf("%d", &n) */
a =malloc(n * sizeof *a);
for (i = 0; i < n; i++)
a[i] = (double*)malloc(m * sizeof(double));
b = malloc(m * sizeof *b);
x = malloc(m * sizeof *x) ;
f = malloc(m * sizeof *f) ;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
printf("a[%d][%d]=", i, j);
scanf("%le", &a[i][j]);
if(fabs(a[i][i])<1.e-10) return 0 ;
}
printf("\n") ;
}
printf("\n") ;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
printf("a[%d][%d]=%le ", i, j, a[i][j]);
}
printf("\n") ;
}
for (j = 0; j < m; j++) {
printf("x[%d]=", j);
scanf("%le", &x[j]);
} //intial guess
printf("\n") ;
for (j = 0; j < m; j++) {
printf("b[%d]=", j);
scanf("%le", &b[j]);
}
printf("\n") ;
while (1) {
bool = 0;
for (i = 0; i < n; i++) {
c = 0.0;
for (j = 0; j < m; j++)
if (j != i)
c += a[i][j] * x[j];
f[i] = (b[i] - c) / a[i][i];
}
for (i = 0; i < m; i++)
if (fabs(f[i] - x[i]) > eps)
bool = 1;
if (bool == 1)
for (i = 0; i < m; i++)
x[i] = f[i];
else if (bool == 0)
break;
}
for (j = 0; j < m; j++)
printf("%le\n", f[j]);
return 0;
}
The condition of stoping the loop is that previous approximation minus current approximation for all x is less than epsilon.
It seems like i did everything according to algorithm,but the programm doesn't work.
Where did i make a mistake?
While not the most strict condition, the usual condition requiered to guarantee convergence in the Jacobi and Gauss-Seidel methods is diagonal dominance,
abs(a[i][i]) > sum( abs(a[i][j]), j=0...n-1, j!=i)
This test is also easy to implement as a check to run before the iteration.
The larger the relative gap in all these inequalities, the faster the convergence of the method.
I've been trying to sort columns in a matrix (the dimensions are m,n <= 10) via the lexicographical order (if the columns share the same element, then we compare the elements in the row beneath etc.) with some additional conditions. I need to use functions to print the matrix, input random integers up to 5 as its elements and finally arrange the matrix. I think I got the printing and random inputs correctly but I can't figure out the sorting. Plus I can't use global variables which I have no idea how to do, since I haven't been shown. An example matrix would be :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m, n;
int mat[10][10];
void print_matrix()
{
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
void random_int()
{
int i, j;
srand((unsigned)time(NULL));
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
mat[i][j] = rand() % 5;
}
}
}
void arrange()
{
int i, j, k, a;
for (j = 0; j < n; ++j)
{
for (i = 0; i < m; ++i)
{
for (k = i + 1; k < m; ++k)
{
if (mat[i][j] < mat[k][j])
{
a = mat[i][j];
mat[i][j] = mat[k][j];
mat[k][j] = a;
}
}
}
}
}
printf("Input the number of rows : ");
scanf("%d", &m);
printf("Input the number of columns: ");
scanf("%d", &n);
random_int(mat[m][n]);
print_matrix(mat[m][n]);
arrange(mat[m][n]);
print_matrix(mat[m][n]);
return 0;
}
Try this solution(will work for input 0-8 only), also used global variables:
There have multiple solutions. but is the easiest one.
I have converted each of the columns as an integer value. then bubble sorted the integers. After sorting. I have then converted the integer value to digits. (You have to know how to convert individual digits to multiple digit integer and multiple digit integers to single-digit.
Note I have added one(1) with each digit. Because the input can be zero(0). if you convert 0 0 2 1 to an integer will be only 21. the first two digits lost. So I have added 1. so 0 0 2 1 will be converted to 1132. I have done (added 1) for each input(deducted 1 after sorting). so it will not affect other inputs. Be careful input have to be from(0 to 8)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int m, n;
int mat[10][10];
int generatedNumber[10];
void print_matrix()
{
printf("The matrix is:\n");
int i, j;
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
printf("%d ", mat[i][j]);
}
printf("\n");
}
}
void random_int()
{
int i, j;
srand((unsigned)time(NULL));
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
{
mat[i][j] = rand() % 5;
}
}
}
void arrange()
{
int i, j, k, a;
for (j = 0; j < n; ++j)
{
int number = 0;
for (i = 0; i < m; ++i)
{
number = number * 10 + mat[i][j] + 1;///Adding one for avoiding zero(0)
}
generatedNumber[j] = number;
}
for(i = 0; i < n; i++)
{
for(j = 0; j < n-i-1; j++)
{
if( generatedNumber[j] > generatedNumber[j+1])
{
// swap the elements
int temp = generatedNumber[j];
generatedNumber[j] = generatedNumber[j+1];
generatedNumber[j+1] = temp;
}
}
}
for(i = 0; i < n; i++)///columwise
{
int generatedColumnvalue = generatedNumber[i];
for(j = m -1; j>= 0; j--)///row wise and fro last vaue to first
{
mat[j][i] = (generatedColumnvalue%10)-1;///removing extra added 1
generatedColumnvalue/=10;
}
}
}
int main()
{
printf("Input the number of rows : ");
scanf("%d", &m);
printf("Input the number of columns: ");
scanf("%d", &n);
random_int();
print_matrix();
arrange();
print_matrix();
return 0;
}
I have taken two 2d arrays but the output is very different from expected.It should merge two 2d arrays into one 1d array.I want to merge two arrays.Not add.Everywhere the information and examples are about merging two 1D arrays.Please help someone.I don't know where I am wrong.
#include <stdio.h>
void print(int a[][3],int m);
int main()
{
int array1[3][3];
int array2[3][3];
int arraySum[6][3];
int k = 0; //put into array;
int l = 10;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
array1[i][j] = ++k; //fill from 1 to 10
array2[i][j] = ++l; //fill from 11 - 19
}
}
/*merge arrays*/
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 3; j++)
{
(i < 3) ? arraySum[i][j] = array2[i][j] : arraySum[i][j] = array1[i-3][j];
//fill arraySum with array2 and append with array1.
//just so that arraySum does not have any order
}
}
printf("Arrays before sorting");
printf("Array 1: ");
print(array1,3);
printf("Array2: ");
print(array2,3);
printf("arraySum");
print(arraySum,6);
/* bubble sort*/
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 3; j++)
{
for(int k = i+1; k < 6; k++)
{
for(int m = 0; m < 3; m++)
{
if(arraySum[i][j] > arraySum[k][m])
{
//swap
int temp = arraySum[i][j];
arraySum[i][j] = arraySum[k][m];
arraySum[k][m] = temp;
}
}
}
}
}
printf("\n\n Merged Array after sorting");
print(arraySum,6);
return 0;
}
void print(int a[][3],int m)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < 3; j++)
{
printf("%d" , a[i][j]);
}
}
}
I want to merge two arrays.Not add.Everywhere the information and examples are about merging two 1D arrays.Please help someone.I don't know where I am wrong.
Please try this code,To Merge two 2d arrays into one 1d array in C
#include <stdio.h>
void print(int a[][3],int m);
int main()
{
int array1[3][3];
int array2[3][3];
int arraySum[6][3];
int k = 0; //put into array;
int l = 10;
for(int i = 0; i < 3; i++)
{
for(int j = 0; j < 3; j++)
{
array1[i][j] = ++k; //fill from 1 to 10
array2[i][j] = ++l; //fill from 11 - 19
}
}
/*merge arrays*/
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 3; j++)
{
(i < 3) ? (arraySum[i][j] = array2[i][j]) : (arraySum[i][j] = array1[i-3][j]);
//fill arraySum with array2 and append with array1.
//just so that arraySum does not have any order
}
}
printf("Arrays before sorting");
printf("Array 1: ");
print(array1,3);
printf("Array2: ");
print(array2,3);
printf("arraySum");
print(arraySum,6);
/* bubble sort*/
for(int i = 0; i < 6; i++)
{
for(int j = 0; j < 3; j++)
{
for(int k = i+1; k < 6; k++)
{
for(int m = 0; m < 3; m++)
{
if(arraySum[i][j] > arraySum[k][m])
{
//swap
int temp = arraySum[i][j];
arraySum[i][j] = arraySum[k][m];
arraySum[k][m] = temp;
}
}
}
}
}
printf("\n\n Merged Array after sorting");
print(arraySum,6);
return 0;
}
void print(int a[][3],int m)
{
for(int i = 0; i < m; i++)
{
for(int j = 0; j < 3; j++)
{
printf("%d" , a[i][j]);
}
}
}
I hope this code will be usefull.
Thank you.
I believe you're trying to be too smart with ternary operator, you can do it simpler way:
if (i < 3)
arraySum[i][j] = array2[i][j];
else
arraySum[i][j] = array1[i-3][j];
Listen to your compiler it would've told you what was wrong if you've compiled with -Wall -Wextra.
And if you insist on using ternary then this would probably be clearer:
arraySum[i][j] = (i < 3) ? array2[i][j] : array1[i-3][j];
I need to know a method to keep duplicate numbers from being stored in a new array when taking numbers from two different arrays. The function is supposed to store each 'unique' value once and not store duplicate values again.
Here is my function code so far:
int * arrayIntersect(int *sizeOfResult, const int *a, const int *b, int sizeOfA, int sizeOfB){
int i;
int j;
int k = 0;
int c[(sizeOfA + sizeOfB)];
for(j = 0; j < sizeOfB; j++){
for(i = 0; i < sizeOfA; i++){
if(a[i] == b[j]){
c[k] = a[i];
(*sizeOfResult)++;
k++;
}
}
}
int *d = (int *)malloc(sizeof(int) * *sizeOfResult);
for(i = 0; i < *sizeOfResult; i++){
d[i] = c[i];
}
return d;
}
It prints the values I need, but I want to eliminate the same number from showing up multiple times when printing the contents of the new dynamic array.
Any idea on how to improve my code to allow prevent duplication?
The proper way to do it is having the arrays ordered and then doing a binary search for each insertion like #Murilo Vasoncelos pointed out.
Below is a quick and dirty solution that loops through a and b and for each iteration checks if the number has been inserted before. If it isn't, it inserts it.
int duplicate = 0;
*sizeOfResult = 0;
for(j = 0; j < sizeOfA; j++){
for(i = 0; i < (*sizeOfResult); i++){
if(c[i] == a[j]){
duplicate = 1;
break;
}
}
if (!duplicate)
{
c[(*sizeOfResult)] = a[i];
(*sizeOfResult)++;
}
duplicate = 0;
}
for(j = 0; j < sizeOfB; j++){
for(i = 0; i < (*sizeOfResult); i++){
if(c[i] == b[j]){
duplicate = 1;
break;
}
}
if (!duplicate)
{
c[(*sizeOfResult)] = b[i];
(*sizeOfResult)++;
}
duplicate = 0;
}
If your arrays a and b are ordered, you can simply use this linear algorithm for array intersection:
int* inter(int* szr, int* a, int* b, int sza, int szb)
{
int c[MAX(sza, szb)];
int i, j, k = 0;
for (i = 0, j = 0; i < sza && j < szb;) {
if (a[i] == b[j]) {
if (k == 0 || c[k - 1] < a[i]) {
c[k++] = a[i];
}
i++;
j++;
}
else if (a[i] < b[j]) {
i++;
}
else {
j++;
}
}
*szr = k;
int* ans = (int*)malloc(sizeof(int) * k);
for (i = 0; i < k; ++i) {
ans[i] = c[i];
}
return ans;
}