I am learning c and encountered maximum cost path question in which
Rules:
matrix is n x n size
Starting from the cell (bottommost leftmost cell), you want to go to the topmost
rightmost cell in a sequence of steps. In each step, you can go either right or up from
your current location.
I tried to solve using dynamic programming and this is the function I have written
computecost(int *utr,int n)//utr is the input matrix
{
int *str;
int i,j;
str=(int *)malloc(n*n*sizeof(int));
for(j=0;j<n;j++)//intialization of bottom row
{
str[n*(n-1)+j]=utr[n*(n-1)+j];
}
for(i=n-2;i>=0;i--)
{
for(j=0;j<n;j++)
{
str[n*i+j]=utr[n*i+j]+max(str[n*(i+1)+j],str[n*(i+1)+(j+1)]);
}
}
printf("%d",str[n*0+0]);
return 0;
}
and this is the input
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&str[n*i+j]);
}
}
but
for the matrix 5 x5
1 4 8 2 9
32 67 18 42 1
4 86 12 7 1
8 4 12 17 44
1 43 11 45 2
the desired output is 272 but I am getting 211.
the output matrix for my case
1 43 11 45 2
51 47 57 62 46
55 143 74 69 47
175 210 92 111 52
211 214 119 113 64
Can anyone help me?
You don't need dynamic programming for this since there are no overlapping sub-problems. Just use a simple recursion.
const int n = 5;
int mat[n][n] = {
{1,4,8,2,9},
{32,67,18,42,1},
{4,86,12,7,1},
{8,4,12,17,44},
{1,43,11,45,2}
}; // input matrix
int f(int x, int y, int sum){
if(x == 0 && y == 4)
return sum;
int p = 0, q = 0;
if(x - 1 >= 0)
p = f(x-1, y, sum + mat[x-1][y]);
if(y + 1 <= 4)
q = f(x, y+1, sum+mat[x][y+1]);
return max(p,q);
}
int main(){
int maxSum = f(4,0, mat[4][0]);
printf("%d\n", maxSum);
}
You were not very far to succeed.
In practice, you did not initialize correctly the bottom row.
Moreover, there was a little mistake in the iteration calculation.
This is the corrected code.
As said in a comment, it could be further simplified, by avoiding the use of a new array, simply updating the input array.
#include <stdio.h>
#include <stdlib.h>
int max (int a, int b) {
return (a > b) ? a : b;
}
int computecost(int *utr,int n) { //utr is the input matrix
int *str;
str = malloc (n*n*sizeof(int));
str[n*n - 1] = utr[n*n - 1];
for (int j = n-2; j >= 0; j--) { //intialization of bottom row {
str[n*(n-1)+j] = utr[n*(n-1)+j] + str[n*(n-1)+j+1]; // corrected
}
for (int i=n-2; i>=0; i--) {
str[n*i+n-1] = utr[n*i+n-1] + str[n*(i+1)+n-1];
for(int j = n-2; j >= 0; j--) {
str[n*i+j] = utr[n*i+j] + max(str[n*(i+1)+j],str[n*i + j+1]); // corrected
}
}
int cost = str[0];
free (str);
return cost;
}
int main() {
int A[25] = {
1,43,11,45,2,
8,4,12,17,44,
4,86,12,7,1,
32,67,18,42,1,
1,4,8,2,9
};
int ans = computecost (A, 5);
printf ("%d\n", ans);
return 0;
}
Related
This question already has answers here:
Pascal's Triangle in C
(4 answers)
Closed 1 year ago.
I tried to code a program that will give the pascal triangle without using arrays and keeping in mind the formula that each element of the pascal triangle can be calculated as n choose k" and written like this:
n choose k = n! / k!(n-k)!
(for both n and k starting from 0)
so I also had to define the factorial function and it worked for the first 14 lines.
but in line 15 and more my numbers started to decrease and became also negative but I don't understand why this happened.
Here is the code:
#include <stdio.h>
int factorial(int a);
int main()
{
int row, j, i, space, tot;
scanf("%d", &row);
space=row;
for(i=0; i<row; i++)
{
for(space=0; space<row-i; space++)
{ printf(" "); }
for (j = 0; j <= i; j++)
{
if (j == 0 || i == 0)
{ tot=1; }
else
{
int n=factorial(i);
int k=factorial(j);
int z=factorial(i-j);
tot= n/(k*z);
}
printf("%6d", tot);
}
printf("\n");
}
}
int factorial(int a)
{
int fact=1;
for (int m=1; m<=a; m++)
{ fact*=m; }
return fact;
}
this is my output in line 15:
1 0 1 5 14 29 44 50 44 29 14 5 1 0 1
but the actual output should be this:
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1
I couldn't find the problem so I would be happy and thankful if anyone could help me.
If you don't care much about computation time then you could compute coefficient directly from their recursive definition.
int pascal(int x,int y) {
if (x==0 || y==0) return 1;
return pascal(x-1,y)+pascal(x,y-1);}
I'm just not able to see where's the error on my code, I am getting 26249 (or 26247 if I go back one spiral level), but it should be 26241.
Obviously, there must be a problem with my logic, but I can't point out where.
Spiral Primes, Project Euler Problem 58
Starting with 1 and spiralling anticlockwise in the following way, a square spiral with side length 7 is formed.
37 36 35 34 33 32 31
38 17 16 15 14 13 30
39 18 05 04 03 12 29
40 19 06 01 02 11 28
41 20 07 08 09 10 27
42 21 22 23 24 25 2643 44 45 46 47 48 49
It is interesting to note that the odd squares lie along the bottom right diagonal, but what is more interesting is that 8 out of the 13 numbers lying along both diagonals are prime; that is, a ratio of 8/13 ≈ 62%.
If one complete new layer is wrapped around the spiral above, a square spiral with side length 9 will be formed. If this process is continued, what is the side length of the square spiral for which the ratio of primes along both diagonals first falls below 10%?
#include <stdio.h>
#define print(ref) printf(#ref" = %d\n",ref);
#define printl(ref) printf(#ref" = %ld\n",ref);
#define NUM_OF_PRIMES 5000
int primesOnThisLevel(int);
void generatePrimes();
int isPrime(int);
int canBeExpressedAsPrime(int);
int primes[NUM_OF_PRIMES] = {2,3,5};
int primesFound = 3;
int main(){
int numbersInDiagonal = 1;
int primesInDiagonal = 0;
int level;
generatePrimes();
for (level = 2 ; numbersInDiagonal/10 <= primesInDiagonal ; level++){
primesInDiagonal += primesOnThisLevel(level);
numbersInDiagonal += 4;
}
print(numbersInDiagonal)
print(primesInDiagonal)
int sideLenght = (2*level)-1;
print(sideLenght*sideLenght);
print(sideLenght);
return 0;
}
int primesOnThisLevel(int level){
int primesCount = 0;
int sideLenght = (2*level)-1;
int differenceBetweenCorners = 2*(level-1);
int cornerValue = sideLenght*sideLenght;
for (int i = 0 ; i < 3 ; i++){
cornerValue -= differenceBetweenCorners;
primesCount += isPrime(cornerValue);
}
return primesCount;
}
void generatePrimes(){
for (int i = 7 ; primesFound < NUM_OF_PRIMES ; i +=2 ){
if ( isPrime(i) ){
primes[primesFound++] = i;
}
}
print(primes[primesFound-1]);
}
int isPrime(int prospect){
if ( prospect == 3 || prospect == 5 ) return 1;
if ( !canBeExpressedAsPrime(prospect) ) return 0;
for (int i = 0 ; primes[i]*primes[i] <= prospect ; i++)
if ( prospect%primes[i] == 0 ) return 0;
return 1;
}
int canBeExpressedAsPrime(int prospect){
if ( prospect%6 == 1 ) return 1;
if ( prospect%6 == 5 ) return 1;
return 0;
}
Special Thanks to Roberto Trani whom pointed out the error which was regarding boundaries, the previous limit included 10% which was not supposed to happen, here it is the ammended main function, which is the perfect situation to use a do-while loop.
int main(){
int numbersInDiagonal = 1;
int primesInDiagonal = 0;
int level = 2;
generatePrimes();
do {
primesInDiagonal += primesOnThisLevel(level);
numbersInDiagonal += 4;
level++;
} while ( numbersInDiagonal < primesInDiagonal*10 );
int sideLenght = (2*(--level))-1;
print(sideLenght);
return 0;
}
I am trying to delete first 20 columns from each of the slices of my 3D dynamic array. I guessed trying to write a function for 2D dynamic array would solve the problem which I would iterate over each of the levels of 3D array. I got an example in stackoverflow which I am trying to make work.
But the problem is the function can not delete the whole column. Instead it only delete one element. Can anyone give me idea how to delete whole column from a 2D dynamic array?
void removeColumn(int** matrix, int col){
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
while(col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][col]=matrix[i][col+1];
col++;
} matrix[i] = realloc(matrix[i], sizeof(double)*MATRIX_WIDHT); }
My expected ouput is like
Sample input:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
sample output:
1 3 4
5 7 8
9 11 12
13 15 16
Update: here is the code which delete the column completely after using #frslm advice
but matrix is not resizing.
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
int** fill(size_t rows, size_t cols, int input[][cols])
{
int i,j,count=1;
int** result;
result = malloc((rows)*sizeof(int*));
for(i=0;i<rows;i++)
{
result[i]=malloc(cols*sizeof(int));
for(j=0;j<cols;j++)
{
result[i][j]=count++;
}
}
return result;
}
void printArray2D(size_t rows, size_t cols,int** input)
{
int i,j;
for(i=0;i<rows;i++)
{
for(j=0;j<cols;j++)
{
printf(" %4d",input[i][j]);
}
printf("\n");
}
}
void removeColumn(int** matrix, int col2del , int rows, int cols){
int MATRIX_WIDTH = cols;
int MATRIX_HEIGHT = rows;
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
int curr_col = col2del;
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
//matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
matrix[i] = realloc(matrix[i], sizeof (matrix[i][0])*MATRIX_WIDTH);
}
}
int main()
{
int arRow,arCol;
arRow =8;
arCol = 9;
int ar[arRow][arCol];
int **filled;
filled = fill(arRow, arCol, ar);
printArray2D(arRow,arCol,filled);
removeColumn(filled, 3,arRow,arCol);
printf("After 3rd Column Delete.......\n");
printArray2D(arRow,arCol,filled);
return(0);
}
Output: last column duplicates
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18
19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63
64 65 66 67 68 69 70 71 72
After 3rd Column Delete.......
1 2 3 5 6 7 8 9 9
10 11 12 14 15 16 17 18 18
19 20 21 23 24 25 26 27 27
28 29 30 32 33 34 35 36 36
37 38 39 41 42 43 44 45 45
46 47 48 50 51 52 53 54 54
55 56 57 59 60 61 62 63 63
64 65 66 68 69 70 71 72 72
You increment col until it reaches the end of the first row, but you never reset it for subsequent rows, which is why you end up removing only the first row's column.
Make sure you reset col at the start of each iteration:
void removeColumn(int** matrix, int col){
MATRIX_WIDTH--;
for(int i=0;i<MATRIX_HEIGHT; i++) {
int curr_col = col; // <- use a temporary `col` variable for each row
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
matrix[i] = realloc(matrix[i], sizeof(int)*MATRIX_WIDTH); // <- int, not double
}
}
Edit (in response to OP's edit):
Ensure that removeColumn() updates the number of columns (cols) after resizing the matrix; one way to do that is by using a pointer: int *cols as a parameter instead of int cols (don't forget to pass in an address, &arCol, when calling this function). Also, I suggest getting rid of the unnecessary MATRIX_HEIGHT variable:
void removeColumn(int** matrix, int col2del, int rows, int *cols){
int MATRIX_WIDTH = --(*cols);
for(int i=0;i<rows; i++) {
int curr_col = col2del;
while(curr_col<MATRIX_WIDTH)
{
//move data to the left
matrix[i][curr_col]=matrix[i][curr_col+1];
curr_col++;
}
matrix[i] = realloc(matrix[i], sizeof(matrix[i][0])*MATRIX_WIDTH);
}
}
It's easier if you pass the width and height, and update the width:
void removeColumn(int** matrix, int col, int* width, int height)
{
int j, i;
for (j = 0; j < height; ++j) {
if (col == *width-1) {
continue;
}
for (i = col; i < *width; ++i) {
matrix[j][i] = matrix[j][i+1];
}
// this is not necessary, but I'm adding as requested
matrix[j] = realloc(
matrix[j],
sizeof(int) * (*width - 1)
);
}
--(*width);
}
You could also avoid dynamic memory allocations, avoiding memory defragmentation:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int max_width, max_height;
int width, height;
int* values;
} matrix;
void removeColumn(matrix* matrix, int col)
{
int y, i;
for (y = 0; y < matrix->height; ++y) {
if (col == matrix->width-1) {
continue;
}
i = col + matrix->height * y;
while (i < matrix->width) {
matrix->values[i] = matrix->values[++i];
}
}
--matrix->width;
}
void printMatrix(matrix* matrix)
{
int y, x;
for (y = 0; y < matrix->height; ++y) {
for (x = 0; x < matrix->width; ++x) {
printf("%d ", matrix->values[x + matrix->width * y]);
}
printf("\n");
}
}
int main ()
{
int y, x = 0;
matrix matrix;
matrix.max_width = 4;
matrix.max_height = 4;
matrix.width = 4;
matrix.height = 4;
int values[4][4];
matrix.values = &values;
for (y = 0; y < matrix.height; ++y) {
for (x = 0; x < matrix.width; ++x) {
int i = x + matrix.width * y;
matrix.values[i] = i % 10;
}
}
printMatrix(&matrix);
removeColumn(&matrix, 1);
printf("===\n");
printMatrix(&matrix);
}
Tested using: https://www.tutorialspoint.com/compile_c_online.php
ADDED
But when the array size is too big then do we have any other option
but using dynamic array
If you want to make a resizable array, you could use a single malloc when allocating the array and use a realloc when the width will be greater than max_width or the height will be greater than max_height.
Nevertheless, I believe we should try to avoid lots of dynamic allocations using malloc or realloc, because they're slow (though most of the time you won't notice), they can severely defragment memory and the way you did it generates lots of unnecessary cache misses.
You should also grow them more than required, for instance, exponentially, if you don't know that you will need to resize the array several times. That's how hashes and dynamic arrays are usually implemented (properly).
You may find, for instance, several JSON, XML and HTML C libraries without dynamic memory to avoid its pitfalls, and in many professional video games, a huge malloc might be used to avoid lots of them and simple arrays are used liberally.
Why is realloc eating tons of memory?
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
http://gameprogrammingpatterns.com/data-locality.html
https://codefreakr.com/how-is-c-stl-implemented-internally/
http://gamesfromwithin.com/start-pre-allocating-and-stop-worrying
CppCon 2014: Mike Acton "Data-Oriented Design and C++"
Of course, you can use dynamic memory, but it's better to understand its pitfalls for better decisions.
I've tried to solve problem 2 on Project Euler in C. This is the first possible solution that came to my mind, and, in fact, it gives as an output the right answer. The problem is that each time I run my program it gives me a different output, which is either "2" or "4613732" that is the right answer. Sorry for my poor english, can you help me find out what's wrong?
#include <stdio.h>
int main(){
int n, n1 = 1, n2 = 2, sum = 2;
while(n<4000000){
n = n1 + n2; /*calculate the next number of the series*/
n1 = n2;
n2 = n;
if(n%2 == 0){
sum = sum + n; /*if the number it's even add it to the main sum*/
}
}
printf("The sum is %d\n", sum);
}
You didn't initialize n; when you get the right answer, it means you got lucky.
#include <conio.h>
#include <iostream>
using namespace std;
int evenFibSum(int i=1,int j=2)
{
const int max = 3999999;
int eventsum = 2;
int sum = 0;
while (sum < max)
{
sum = i + j;
i = j;
j = sum;
if (sum % 2 == 0)
eventsum +=sum;
}
return eventsum;
}
For more efficient solution apply following logic
Fibbonaci Series => 1 2 3 5 8 13 21 34 55 89 144
Index => 0 1 2 3 4 5 6 7 8 9 10
To get even fibbonanci addition I have to add following index values[1 4 7 10]
Here I am sensing some pattern
[1 4 7 10] => I need advance index by 3
so how to advance index by 3
// k = i+j = > 3 13 55
// i = k+j => 5 21 89
// j = k+i => 8 34 144
int evenFibSumx(int i=1,int j=2)
{
const int max = 3999999;
int eventsum = 2;
int k= 0;
while (1)
{
k = i + j;
i = k + j;
j = k + i;
if(i >= max)
break;
if (j%2 == 0)
eventsum +=j;
}
return eventsum;
}
int main()
{
std::cout << evenFibSum();
std::cout << evenFibSumx();
}
So I have this code that randomly generates an integer array based on user input, and puts the elements in ascending and descending order. However, currently, the code only prints the descending order twice. So I would like to know how to make a copy of the array ascd and use the copy in the piece of code that organizes the descending order. I am just a beginner, so I apologize if this is a silly question, and appreciate all the guidance I can get. Here is my code:
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
int main (){
int x;
printf("Enter the size of your array\n");//User is entering number of elements
scanf("%d", &x);
int ascd[x]; //Array
int c;
int d;
int e;
int kk = 0;
int temp;
int tempother;
int turtle;
for(c = 0; c<x; c++){//Randomly generating elements
srand(time(0));
ascd[kk] = (rand() %100) + 1;
}
for(c = 0; c<x; c++){ //Ascending order
for(d = 0; d<(x-c-1); d++){
if(ascd[d] > ascd[d+1]){
temp = ascd[d];
ascd[d] = ascd[d+1];
ascd[d+1] = temp;
}
}
}
for(turtle = 0; turtle<x; turtle++){//Descending order
for(e = 0; e<(x-turtle-1); e++){
if(ascd[e] < ascd[e+1]){
tempother = ascd[e];
ascd[e] = ascd[e+1];
ascd[e+1] = tempother;
}
}
}
printf("The ascending order is\n\n");
for(c = 0; c<x; c++){
printf("%d\n", ascd[c]);
}
printf("\n\nThe descending order is\n\n");
for(turtle = 0; turtle<x; turtle++){
printf("%d\n", ascd[turtle]);
}
}
There are a number of additional issues you need to consider. First always, always, validate user input. If nothing else, with the scanf family of functions, make sure the expected number of conversions were successfully performed. e.g.
int x = 0;
printf ("\n enter the number of elements for your array: ");
if (scanf ("%d", &x) != 1) { /* always validate user input */
fprintf (stderr, "error: invalid input, integer required.\n");
return 1;
}
int ascd[x], desc[x];
Next, you only need to seed the random number generator once. Move srand (time (NULL)); out of the loop.
While not a requirement, it is good practice to initialize your VLA's to all zero (or some number, since you cannot provide an initializer) to eliminate the chance of an inadvertent read from an uninitialized value when iterating over the array (you can consider your filling in this case an initialization, making the memset optional here, but you won't immediately loop and fill in all cases. Something as simple as the following is sufficient if you are not immediately filling the array, e.g.
memset (ascd, 0, x * sizeof *ascd); /* good idea to zero your VLA */
After filling your array, a simple memcpy will duplicate the array if you wish to preserve both ascending and descending sorts, e.g.
for (int i = 0; i < x; i++) /* x random values 1 - 100 */
ascd[i] = (rand () % 100) + 1;
memcpy (desc, ascd, x * sizeof *ascd); /* copy ascd to desc */
The remainder is just a bit of cleanup. Resist the urge to create a (variable next) for every value in your code. That quickly becomes unreadable. While I prefer the C89 declarations, the C99/C11 declarations inside the for block are convenient, e.g.:
for (int i = 0; i < x; i++) /* ascending order */
for (int j = 0; j < (x - i - 1); j++)
if (ascd[j] > ascd[j + 1]) {
int temp = ascd[j];
ascd[j] = ascd[j + 1];
ascd[j + 1] = temp;
}
Putting all the pieces together, and noting that main() is type int and therefore will return a value, you could tidy things up as follows. Your style is completely up to you, but the goal should be readability. e.g.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main (void) {
int x = 0;
printf ("\n enter the number of elements for your array: ");
if (scanf ("%d", &x) != 1) { /* always validate user input */
fprintf (stderr, "error: invalid input, integer required.\n");
return 1;
}
int ascd[x], desc[x];
srand (time (NULL)); /* you only need do this once */
memset (ascd, 0, x * sizeof *ascd); /* good idea to zero your VLA */
for (int i = 0; i < x; i++) /* x random values 1 - 100 */
ascd[i] = (rand () % 100) + 1;
memcpy (desc, ascd, x * sizeof *ascd); /* copy ascd to desc */
for (int i = 0; i < x; i++) /* ascending order */
for (int j = 0; j < (x - i - 1); j++)
if (ascd[j] > ascd[j + 1]) {
int temp = ascd[j];
ascd[j] = ascd[j + 1];
ascd[j + 1] = temp;
}
for (int i = 0; i < x; i++) /* descending order */
for (int j = 0; j < (x - i - 1); j++)
if (desc[j] < desc[j + 1]) {
int temp = desc[j];
desc[j] = desc[j + 1];
desc[j + 1] = temp;
}
printf ("\n the ascending order is\n\n");
for (int i = 0; i < x; i++) {
if (i && !(i % 10)) putchar ('\n');
printf (" %3d", ascd[i]);
}
printf ("\n\n the descending order is\n\n");
for (int i = 0; i < x; i++) {
if (i && !(i % 10)) putchar ('\n');
printf (" %3d", desc[i]);
}
putchar ('\n');
return 0;
}
Example Use/Output
$ ./bin/sort_copy
enter the number of elements for your array: 100
the ascending order is
1 1 4 4 5 5 7 8 8 9
10 13 16 16 17 20 22 22 22 23
24 24 25 27 29 29 33 35 35 35
37 38 40 41 41 41 41 42 44 45
46 48 48 48 49 50 53 54 56 57
58 59 61 61 63 64 65 65 66 66
67 68 68 70 71 73 74 74 74 75
76 80 80 80 80 82 84 84 85 85
85 85 86 88 88 89 89 90 91 91
91 92 92 93 93 93 96 99 100 100
the descending order is
100 100 99 96 93 93 93 92 92 91
91 91 90 89 89 88 88 86 85 85
85 85 84 84 82 80 80 80 80 76
75 74 74 74 73 71 70 68 68 67
66 66 65 65 64 63 61 61 59 58
57 56 54 53 50 49 48 48 48 46
45 44 42 41 41 41 41 40 38 37
35 35 35 33 29 29 27 25 24 24
23 22 22 22 20 17 16 16 13 10
9 8 8 7 5 5 4 4 1 1
Look things over and let me know if you have any questions.
Sorting with qsort
Continuing for the comment, qsort is an optimized sorting routine that is part of the C standard library (in stdlib.h) and is the go-to sort function regardless of the type of data you have to sort. The only requirement that generally catches new C programmers is the need to write a comparison function to pass to qsort so that qsort knows how you want the collection of objects sorted. qsort will compare two elements by passing a pointer to the values to the compare function you write. The declaration for the comparison is the same regardless of what you are sorting, e.g.
int compare (const void *a, const void *b);
You know you are sorting integer values, so all you need to do to sort ascending is to write a function that returns a positive value if a > b, returns zero if they are equal, and finally returns a negative value if b > a. The simple way, is to write
int compare (const void *a, const void *b) {
int x = *(int *)a;
int y = *(int *)b;
return x - y;
}
That satisfies the sort requirement for ascending order, and to sort in descending order return y - x; -- but there is a problem. If x and y happen to be large positive and large negative values, there is a potential that x - y will exceed the maximum (or minimum) value for an integer (e.g. overflow, because the result will not fit in an integer value).
The solution is simple. You can perform the same comparison, but using the results of an inequality, e.g. returning (a > b) - (a < b) for the ascending comparison, and (a < b) - (a > b) for the descending comparison. (this scheme will work for all numeric types, you just need to adjust the cast). Step though the inequality. In the ascending case, if a > b the return is 1 (e.g. return 1 - 0;). If they are equal, the inequality returns 0 (0 - 0 ), and finally if a < b, the value returned is -1 ( 0 - 1 ).
While you are free to continue to explicitly declare the x and y variables, you will generally see it written with the cast in the comparison, eliminating the need for the x and y variables altogether, e.g.
/* integer comparison ascending (prevents overflow) */
int cmpascd (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
Putting those pieces together, the same program can be written using qsort instead of the inefficient nested loops (and moving the print array routine to a function of its own) as follows,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#define ROW 10
int cmpascd (const void *a, const void *b);
int cmpdesc (const void *a, const void *b);
void prnarr (int *a, int n, int row);
int main (void) {
int x = 0;
printf ("\n enter the number of elements for your array: ");
if (scanf ("%d", &x) != 1) { /* always validate user input */
fprintf (stderr, "error: invalid input, integer required.\n");
return 1;
}
int ascd[x], desc[x];
srand (time (NULL)); /* you only need do this once */
memset (ascd, 0, x * sizeof *ascd); /* good idea to zero your VLA */
for (int i = 0; i < x; i++) /* x random values 1 - 100 */
ascd[i] = (rand () % 100) + 1;
memcpy (desc, ascd, x * sizeof *ascd); /* copy ascd to desc */
qsort (ascd, x, sizeof *ascd, cmpascd); /* qsort ascending */
qsort (desc, x, sizeof *desc, cmpdesc); /* qsort descending */
printf ("\n the ascending order is\n\n");
prnarr (ascd, x, ROW);
printf ("\n\n the descending order is\n\n");
prnarr (desc, x, ROW);
putchar ('\n');
return 0;
}
/* integer comparison ascending (prevents overflow) */
int cmpascd (const void *a, const void *b)
{
/* (a > b) - (a < b) */
return (*(int *)a > *(int *)b) - (*(int *)a < *(int *)b);
}
/* integer comparison descending */
int cmpdesc (const void *a, const void *b)
{
/* (a < b) - (a > b) */
return (*(int *)a < *(int *)b) - (*(int *)a > *(int *)b);
}
void prnarr (int *a, int n, int row)
{
for (int i = 0; i < n; i++) {
printf (" %3d", a[i]);
if (i && !((i + 1) % row))
putchar ('\n');
}
}
As with the first answer, give it a try and let me know if you have any questions. (And remember to always compile with a minimum -Wall -Wextra to enable most compiler warnings -- and fix any warnings generated before you consider your code reliable -- you won't run into any circumstance where warnings can be understood and safely ignored anytime soon) Add -pedantic to see virtually all warnings that can be generated. (if you look up pedantic in Websters, you will see why that name is apt.) Just FYI, the gcc compiler string I used to compile the code was:
$ gcc -Wall -Wextra -pedantic -std=c11 -Ofast -o bin/sort_copy sort_copy.c
You print the final array twice, you can have your ascending array output by printing the values of the array right after you have done the ascending operation.
Create an another array to store descending items. You can reverse the ascending array to create the descending array. Try this code.
#include
#include
#include
#include
int main (){
int x;
printf("Enter the size of your array\n");//User is entering number of elements
scanf("%d", &x);
int ascd[x]; //Array
int desc[x];
int c;
int d;
int e;
int kk = 0;
int temp;
int tempother;
int turtle;
int z=0;
for(c = 0; c<x; c++){//Randomly generating elements
srand(time(0));
ascd[kk] = (rand() %100) + 1;
}
for(c = 0; c<x; c++){ //Ascending order
for(d = 0; d<(x-c-1); d++){
if(ascd[d] > ascd[d+1]){
temp = ascd[d];
ascd[d] = ascd[d+1];
ascd[d+1] = temp;
}
}
}
for(turtle = x-1; turtle>=0; turtle--){//Descending order
desc[z]=ascd[turtle];
z++;
}
printf("The ascending order is\n\n");
for(c = 0; c<x; c++){
printf("%d\n", ascd[c]);
}
printf("\n\nThe descending order is\n\n");
for(turtle = 0; turtle<x; turtle++){
printf("%d\n", desc[turtle]);
}
}