What should I do for sort array? - c

I tried to sort arr by excluding those who were already selected as the largest numbers but it didn't work.
The result is this:
As I intended, at first cycle, the store is {9, 0, 0, 0, 0 ... } and when arr[i] becomes 9, the rest of process should be skipped. I have to sort it without additional functions and it's too difficult to me. What is the problem?
int i = 0;
int j = 0;
int num = 0;
int sign = 0;
int arr[10] = { 1,5,3,4,8,7,5,9,8,0 };
int max = arr[0];
int store[10] = { 0 };
int k = 0;
for (j = 0; j < 10; j++) {
printf("store: ");
for (int n = 0; n < 10; on++)
printf("%d ", store[n]);
printf("\n");
for (i = 0; i < 10; i++) {
sign = 0;
k = 0;
while (k < 10) {
if (arr[i] == store[k]) {
sign = 1;
break;
}
k++;
}
if (sign == 1) {
continue;
}
if (arr[i] > max) {
max = arr[i];
}
}
store[j] = max;
}

You have several errors here:
The array store has a size of 10, but in the jth pass through the outer loop, only j values have been filled in; the rest is still zero. So whenever you iterate over store, you should use j as upper limit.
You are looking for the max in each iteration. Therefore, it is not enough to initialise max once outside the outer loop. You do that, and it will stay 9 ever after. You should reset max for every j.
Finally, your idea to go through the array to see whether you have already processed a certain value does not work. Your array has duplicates, two 8's and two 5's. You will only place one eight and one five with your strategy and re-use the last value of max for the last two elements. (Plus, that idea lead to O(n³) code, which is very wasteful.
You can work around that by keeping an extra array where you store whether (1) or not (0) you have already processed a value at a certain index or by setting processed entries in the array to a very low value.
What you want to implement is selection sort: Find the maximum value in the whole list and move it to the front. Then find the maximum in the whole list except the first item and move it to the second slot and so on:
* 1 5 3 4 8 7 5 9 8 0
9 * 5 3 4 8 7 5 1 8 0
9 8 * 3 4 5 7 5 1 8 0
9 8 8 * 4 5 7 5 1 3 0
9 8 8 7 * 5 4 5 1 3 0
9 8 8 7 5 * 4 5 1 3 0
9 8 8 7 5 5 * 4 1 3 0
9 8 8 7 5 5 4 * 1 3 0
9 8 8 7 5 5 4 3 * 1 0
9 8 8 7 5 5 4 3 1 * 0
9 8 8 7 5 5 4 3 1 0 *
Here, all items to the left of the asterisk have been sorted and everything to the right of the asterisk is still unsorted. When the * (at position j) has moved to the right, the whole array is sorted.
This sort is in-place: It destroys the original order of the array. That is useful, because the position of an element tells us whether it has been processed or not. In the third iteration, the algorithm can distinguish between the 8 that has been sorted and the 8 that hasn't been sorted yet. (This sort is often described as sorting a hand of cards: Look fo the lowest, put it to the left and so on. If you must sort into a second array, copy the original array and sort the copy in place.)
Here's the code that sorts your array and prints out the diagram above:
#include <stdlib.h>
#include <stdio.h>
int main()
{
int arr[10] = {1, 5, 3, 4, 8, 7, 5, 9, 8, 0};
int i = 0;
int j = 0;
for (j = 0; j < 10; j++) {
int imax = j;
int swap = arr[j];
// print array
for (i = 0; i < 10; i++) {
if (i == j) printf("* ");
printf("%d ", arr[i]);
}
printf("\n");
// find index of maximum item
for (i = j + 1; i < 10; i++) {
if (arr[i] > arr[imax]) {
imax = i;
}
}
// swap first unsorted item and maximum item
arr[j] = arr[imax];
arr[imax] = swap;
}
// print fully sorted array
for (i = 0; i < 10; i++) {
printf("%d ", arr[i]);
}
printf("*\n");
return 0;
}

Use i and j.
N is 10 and the data consists of shuffled numbers 0 to N-1.
j goes from 0 to N-1. At each step, you want to fill it with
the maximum of the unprocessed input.
So i goes from j+1 to N-1, in the inner loop. If arr[j] < arr[i],
swap arr[i] and arr[j].
It speeds up considerably as you get towards the end.

Related

Minimize difference in tower heights - TestCase issue

This is the question text:
Given an array arr[] denoting heights of N towers and a positive integer K, you have to modify the height of each tower either by increasing or decreasing them by K only once. After modifying, height should be a non-negative integer.
Find out what could be the possible minimum difference of the height of shortest and longest towers after you have modified each tower.
The question can be found here: https://practice.geeksforgeeks.org/problems/minimize-the-heights3351/1#
My doubt was in the correctness of the algorithm I came up with. Here's the code:
int getMinDiff(int arr[], int n, int k) {
// code here
int mean = 0;
for(int i = 0; i < n; i++)
{
mean += arr[i];
}
mean /= n;
int minH = INT_MAX, maxH = INT_MIN;
for(int i = 0; i < n; i++)
{
if(arr[i] < mean)
{
if(arr[i] + k <= mean)
{
arr[i] += k;
}
else
{
int a = arr[i] + k - mean;
int b = mean - arr[i];
if(a < b)
{
arr[i] += k;
}
}
}
else if(arr[i] > mean)
{
if(arr[i] >= k)
{
if(arr[i] - k >= mean)
{
arr[i] -= k;
}
else
{
int a = arr[i] - mean;
int b = mean - (arr[i] - k);
if(b < a)
{
arr[i] -= k;
}
}
}
}
}
for(int i = 0; i < n; i++)
{
if(arr[i] < minH)
{
minH = arr[i];
}
if(arr[i] > maxH)
{
maxH = arr[i];
}
}
return maxH - minH;
}
The code first finds the mean height of towers, then to minimize the difference, tries to bring height of each tower as close to the mean as possible. Then it calculates the difference between highest and lowest towers' heights.
This code, for the following test case:
K = 5
arr = 2 6 3 4 7 2 10 3 2 1
Produces the output
4
The given answer is
7
But, according to me, we can adjust the array as:
2 6 3 4 2 2 5 3 2 6
Then the minimum and maximum heights are 2 and 6, so the answer should be 4. So, is there something wrong in the way I am approaching this problem?
I know this question has been asked before, but my query is about the specific solution algorithm.
Mean gets skewed by the number of elements having a certain value. But in this problem, the result is independent of how many elements match a particular value; we could have one element equal 20 or 1000 elements equal 20 and it won't affect the result.
2 6 3 4 7 2 10 3 2 1
k = 5
Ordered:
x (optimal)
+5: 6 7 8 9 11 12 15
1 2 3 4 6 7 10
-5: -4 -3 -2 -1 1 2 5
x (optimal)

I want to get the inverse of an array while the user input the value

I create a program that get the input of array element size of 10. Everything getting will with the sum of even and odd number. but when it comes to the inverse it didn't work.
i created two arrays where the first getting the value from the user and second copying the element starting from end of the first array..
#include <stdio.h>
int main (){
int array[10] , i , odd =0 , even =0;
int array1[10],b;
for (i=0 ; i < 10 ; i ++){
printf("Insert number %d: ",i);
scanf("%d",&array[i]);
}
for (i=0; i < 10 ; i++){
if ( array[i] % 2 == 0){
even = even + array[i];
}
else
odd = odd + array[i];
}
printf("\n The Sum of Even Numbers in this Array = %d ", even);
printf("\n The Sum of Odd Numbers in this Array = %d ", odd);
for ( i = 10 , b =0; i>0; i-- , b++)
{
array1[b] = array[i];
}
printf("\nReverse Order:\n");
for ( b = 0 ; b< 10;b++ )
{
printf(" %d",array[b]);
}
return 0;
}
The input will be: 2 3 5 4 6 12 3 7 4 9
What I expect the out put for the reverse is: 9 4 7 3 12 6 4 5 3 2
But it gave me same value as : 2 3 5 4 6 12 3 7 4 9 .
Any Idea for how doing this reverse.?
In addition to the answer by #Yunnosch that identifies the problems in your current implementation, you can refactor (rearrange) your code to sum even and odd and reverse array into array1 in a single loop. The only other loop you need is the loop to iterate over array1 outputting the reversed array.
With a bit of re-arranging, you could do something similar to:
#include <stdio.h>
int main (void) {
int array[] = { 2, 3, 5, 4, 6, 12, 3, 7, 4, 9 }, /* array */
array1[sizeof array/sizeof *array], /* array1 */
even = 0, odd = 0; /* even/odd */
size_t n = sizeof array/sizeof *array; /* no. elem in array */
for (size_t i = 0; i < n; i++) { /* loop over each element in array */
array1[i] = array[n - i - 1]; /* reverse into array1 */
if (array[i] & 1) /* check if odd (bit-0 == 1) */
odd += array[i]; /* add value to odd */
else /* even */
even += array[i]; /* add value to even */
}
/* output results */
printf ("even sum: %d\nodd sum : %d\n\nreversed: ", even, odd);
for (size_t i = 0; i < n; i++)
printf (" %d", array1[i]);
putchar ('\n');
}
(note: you can either use if (array[i] % 2) or if (array[i] & 1) to test whether the element is odd or even. Anding with 1 simply checks whether bit-0 is 1, if it is, it's an odd number. Modern compilers will optimize to remove the division inherent to modulo, so whichever you prefer should pose no penalty)
Example Use/Output
$ ./bin/revarr
even sum: 28
odd sum : 27
reversed: 9 4 7 3 12 6 4 5 3 2
Look things over and let me know if you have questions.
You are outputting the array which you never tried to inverse.
printf(" %d",array[b]);
should be
printf(" %d",array1[b]);
Aside, the input by David C. Rankin:
Also for ( i = 10 ... and array1[b] = array[i]; assigns from beyond the end of array. It should e.g. better be
for ( i = 10 , b =0; i>0; i-- , b++)
{
array1[b] = array[i-1];
}

Not getting all results shifting my array

I'm trying to make a program that shifts all the elements of an array to the right by one and move the last element into the first position. My problem is when I run my code it's giving me the number 5 twice. Can someone help me, maybe my logic or my for loop is not right?
#include <stdio.h>
int main ()
{
int array[6];
int x;
int temp;
printf("Enter six numbers.\n\n");
for (x = 0; x < 6; x++) {
printf("Enter a number : ", x + 1);
scanf("%d", &array[x]);
temp = array[x - 1];
}
for (x = 6 - 1; x > 0; x--) {
array[x] = array[x - 1];
}
array[0] = temp;
for (x = 0; x < 6; x++) {
printf("%d\n", array[x]);
}
return 0;
}
You could make a for loop like
for(i=0; i<SIZE; ++i)
{
scanf("%d", &arr[(i+1)%SIZE]);
}
The (i+1)%SIZE would evaluate to i+1 if i+1 is less than SIZE. Otherwise, it would wrap around.
Or you can
int t=arr[SIZE-1];
for(i=SIZE-1; i>0; --i)
{
arr[i]=arr[i-1];
}
arr[0]=t;
save the last element into a temporary variable, shift other elements towards right and finally assign the first element the value in the temporary variable.
As Gourav pointed out, in the first iteration of your first for loop, arr[x-1] would become arr[-1] as x is 0. You are trying to access memory which is not part of that array. This invokes undefined behavior.
I will try to explain it with the very easiest algorithm and yes easy means not efficient as from performance perspective.
For example, let's say you have an array of six elements:
1 2 3 4 5 6
From the question, all I understood is that you want to reverse this array to have a final array to be:
6 5 4 3 2 1
A naive way of doing is to store the first element in a temporary variable, assign the second element to the first element and after that assign the temporary variable to the second element and repeat this until all elements are swapped as shown below:
temp = arr[0]
arr[0] = arr[1]
arr[1] = temp
You will need two loops to do this, one decrementing and one incrementing
1 2 3 4 5 6 i=0; j=5
2 1 3 4 5 6 i=1; j=5
2 3 1 4 5 6 i=2; j=5
2 3 4 1 5 6 i=3; j=5
2 3 4 5 1 6 i=4; j=5
2 3 4 5 6 1 i=5; j=5
Next, you have to execute the above loop with one less iteration:
2 3 4 5 6 1 i=0; j=4
3 2 4 5 6 1 i=1; j=4
3 4 2 5 6 1 i=2; j=4
3 4 5 2 6 1 i=3; j=4
3 4 5 6 2 1 i=4; j=4
So, the loops would be:
for(i=5; i>0; i--)
{
for(j=0; j<i; j++)
{
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
You can make things a bit more generic by adding a direction to your shift routine and putting the shift code in a function that takes the array, the number of members and the direction to shift as arguments. Then its just a matter of iterating in the proper direction and shifting the elements in the correct direction and putting the final value in the proper place. For example, you could write a simple function as follows:
/** shift array index in in circular manner by 1 in the
* 0 - left or 1 - right direction.
*/
void arrayshift (int *a, size_t nmemb, int dir)
{
if (dir) { /* shift to RIGHT */
int tmp = a[nmemb - 1];
for (size_t i = nmemb - 1; i > 0; i--)
a[i] = a[i - 1];
a[0] = tmp;
}
else { /* shift to LEFT */
int tmp = a[0];
for (size_t i = 1; i < nmemb; i++)
a[i - 1] = a[i];
a[nmemb - 1] = tmp;
}
}
A simple test routine could be:
#include <stdio.h>
enum { LEFT, RIGHT };
void arrayshift (int *a, size_t nmemb, int dir);
int main (int argc, char **argv) {
int a[] = { 1, 2, 3, 4, 5, 6 },
dir = argc > 1 ? LEFT : RIGHT;
size_t n = sizeof a / sizeof *a;
printf ("original:");
for (size_t i = 0; i < n; i++)
printf (" %d", a[i]);
putchar ('\n');
arrayshift (a, n, dir);
printf ("shifted :");
for (size_t i = 0; i < n; i++)
printf (" %d", a[i]);
putchar ('\n');
return 0;
}
/** shift array index in in circular manner by 1 in the
* 0 - left or 1 - right direction.
*/
void arrayshift (int *a, size_t nmemb, int dir)
{
if (dir) { /* shift to RIGHT */
int tmp = a[nmemb - 1];
for (size_t i = nmemb - 1; i > 0; i--)
a[i] = a[i - 1];
a[0] = tmp;
}
else { /* shift to LEFT */
int tmp = a[0];
for (size_t i = 1; i < nmemb; i++)
a[i - 1] = a[i];
a[nmemb - 1] = tmp;
}
}
Example Use/Output
$ ./bin/array_cir_shift_by_1
original: 1 2 3 4 5 6
shifted : 6 1 2 3 4 5
$ ./bin/array_cir_shift_by_1 0
original: 1 2 3 4 5 6
shifted : 2 3 4 5 6 1
You can also pass the number of element to shift the array by and use the modulo operator to help with the indexing. (that is left for another day)

Why is my program not dividing even numbers by two?

It should scan 10 int numbers and then display them backwards, dividing the even ones by two, but it just displays them without dividing.
es:
10 9 8 7 6 5 4 3 2 1 ==> 1 2 3 2 5 3 7 4 9 5
but mine does:
10 9 8 7 6 5 4 3 2 1 ==> 1 2 3 4 5 6 7 8 9 10
#include <stdio.h>
int main(void)
{
int a[10];
for(int i = 0; i < 10; i++)
scanf("%d", &a[i]);
for (int i = 0; i < 10; i++) {
if (a[i] % 2 == 0 ) {
a[i] = a[i] / 2; i++;
}
else
i++;
}
for(int i = 9; i > -1; i--)
printf("%d\n", a[i]);
return 0;
}
The middle loop incorrectly increments i twice per iteration:
for (int i = 0; i < 10; i++) { // <<== One increment
if (a[i]%2 == 0 ) {
a[i] = a[i]/2; i++; // <<== Another increment - first branch
}
else
i++; // <<== Another increment - second branch
}
In your case, all even numbers happen to be stored at even positions that your loop skips.
Note: A better solution is to drop the middle loop altogether, and do the division at the time of printing.
The body of your second for loop advances i. Since it's also advanced in the loop's clause, it's advanced twice, effectively skipping any other element. Remove those advancements, and you should be OK:
for(int i=0; i<10; i++) {
if (a[i] % 2 == 0) {
a[i] /= 2;
}
}
In your program you incrementing the for loop variable i two times inside the loop and loop also increment the value one time so the values are skipped that is the reason you are getting wrong output.herewith i have attached the corrected program and its output.hope you understand the concept .Thank you
#include <stdio.h>
int main(void)
{
int a[10];
printf("\n Given Values are");
printf("\n-----------------");
for(int i = 0; i < 10; i++)
scanf("%d", &a[i]);
for (int i = 0; i < 10; i++)
{
if (a[i] % 2 == 0 )
{
a[i] = a[i] / 2;
}
}
printf("\n After dividing the even numbers by 2 and print in reverse order");
printf("\n ----------------------------------------------------------------\n");
for(int i = 9; i > 0; i--)
printf("%d\n", a[i]);
return 0;
}
Output
Given Values are
-----------------
1
2
3
4
5
6
7
8
9
10
After dividing the even numbers by 2 and print in reverse order
----------------------------------------------------------------
5
9
4
7
3
5
2
3
1

Creating a 2D array board

I am trying to create a 2d matrix board which side is determined by the user input. I created the two D array but it is not printing the right numbers. For example if the user enters 3, it is suppose to create a 3 * 3 board with the number 8, 7, 6, 5, 4, 3, 2, 1, 0.
However it keeps printing the same numbers in each row eg 876, 876, 876
I know it is doing what I have written but I cant figure out how to correct it...I am thinking that I need a counter that resets to zero and perhaps the [i][j] = counter's value.
Anyway here is the code that is giving the trouble.
for (i =0; i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * row)-1) - j;
printf( "%i", game[i][j] );
}
How can I populate the board so it prints from (row * col) - 1 to zero. Thanks a million.
for ((i=0, k=0); i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * col)-1) - (k++);
printf( "%i", game[i][j] );
}
}
The basic mistake in the code is that, in each iteration, the value getting subtracted from the game[i][j] gets re-initialized to 0. Since, the value of (row * col) is constant for a given value of both, subtracting (0, 1, 2) each time from the sum results in the reproduction of the same numbers.
As given in the example, row=3, col=3, so 3*3 = 9 (Indexed from 0 to 8).
So, we do :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
again j gets re-init to 0, so again we have,
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
.
The solution is, the value getting subtracted should get uniformly reduced, such that it doesn't get re-init inside the loop.
Result :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
8 - 3 = 5
.
.
.
.
8 - 8 = 0.
Hope this clears the problem.
As suggested by "self", using a third variable is the easiest way (and actually the most efficient : only one decrement per iteration)
int count = row * col - 1;
for (size_t i =0; i< row; i++)
{
for (size_t j =0; j < col; j++)
{
game [i][j] = count--;
printf( "%i", game[i][j] );
}
}
Output:
24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Resources