arranging numbers in ascending order [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
Why do i need to declare this for loop for i var for so many times, what is the meaning of this j var (for j=i+1;j<n;j++) ?
How do I know that number(i) >number(j). And also a = number[i]; what is the value of number[i] here?
#include <stdio.h>
/*
* C program to accept N numbers and arrange them in an ascending order
*/
void main() {
int i, j, a, n, number[30];
printf("Enter the value of N \n");
scanf("%d", &n);
printf("Enter the numbers \n");
for (i = 0; i < n; ++i) {
scanf("%d", &number[i]);
}
for (i = 0; i < n; ++i) {
for (j = i + 1; j < n; ++j) {
if (number[i] > number[j]) {
a = number[i];
number[i] = number[j];
number[j] = a;
}
}
}
printf("The numbers arranged in ascending order are given below \n");
for (i = 0; i < n; ++i){
printf("%d\n", number[i]);
}
}

This is quite basic program called selection sort.
The wiki article is: Selection sort.
Basically in this program, i is first pointing to the first element in the array. Then, j points to the next element. If, the element j is smaller than element i, they get swapped. After swapping, the inner for loop still continues, and then j points to the next element of what it was pointing to, and again it check if it is smaller, and swaps if it is true.
I think that is being a bit confusing, so I'll now do it with a example.
Let's say we have an array with 3 elements: 4 1 3. i points to the first element that is 4. j points to the second element that is 1. It checks if the element j is smaller than element i. Yes it is, so it swaps them. Now the array is: 143. Then j moves to the next element. It checks if element j is smaller than element i. No. Then, the inner loop finishes. Now, i is pointing to 4 and j is pointing to 3. It check if element j is smaller than element i. Yes, so it swaps them. So now the array is 134. well it continues the process till i is smaller than 3, or the number of elements of the array. Thus, now, the array got sorted in ascending order.
This image has been taken from the link mentioned earlier. Red is current min. Yellow is sorted list. Blue is current item.
Well, the line
a = number [i];
is just copying the value of element i of the array number to the variable a.
The line
number [i] = number [j];
is just copying the value of element j of the number array in its element i.
The line
number [j] = a;
is copying the value of a into the element j of the array number.
Basically, the lines
a = number [i];
number[i] = number [j];
number [j] = a;
are swapping the values of number [i] and number [j].

Related

C program to find the second largest element (also the largest) [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 months ago.
Improve this question
This is the code I wrote and I'm wondering if there is any solution for the way I am thinking(the second number should be < largest and also bigger than the previous number). Thanks and sorry for [duplicate] but I am really curious if there is anything similar.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main()
{
int arr[10];
int i;
int greatest;
int second;
printf("Enter 10 values:");
for (i = 0; i < 10; i++)
{
scanf("\n%d", &arr[i]);
}
greatest = arr[0];
for (i = 1; i < 10; i++)
{
if (greatest < arr[i])
{
greatest = arr[i];
}
}
second = arr[i];
for (i = 0; i < 10; i++)
{
if (arr[i] < greatest && second > arr[i - 1])
{
second = arr[i];
}
}
printf("The greatest number is : %d", greatest);
printf("\nThe second greatest number is: %d", second);
return 0;
}
Your key mistake would be here:
for (i = 1; i < 10; i++)
{
if (greatest < arr[i])
{
greatest = arr[i];
}
}
second = arr[i];
Your loop conditions means that when the loops ends, i must be 10. That means arr[i] is out of bounds. This invokes undefined behavior. We have no way of knowing what the value of second is going into the next loop, and this will potentially affect your results.
You likely meant: second = arr[0] to initialize second with the first element in arr.
Having initialized second properly, you'd want to change that value only if the current element in the list is greater than the existing value for second and smaller than greatest.
In your code you've compared second to arr[i - 1]. When i is 0 on the first iteration, this will give you a negative index.
second = arr[0];
for (size_t i = 1; i < 10; i++) {
if (arr[i] < greatest && arr[i] > second) {
second = arr[i];
}
}
As a general suggestion, you do not need to declare your variables all at the beginning of the function in modern C. Declare them closer to actual use. Additionally, your i variables do not convey useful information beyond the scope of the loops, so scope them to the loops. That would have helped you catch the first out of bounds array access.
The solution
#include <limits.h>
#include <stdio.h>
int main()
{
int n = 5;
int arr[n] = {1, 2, 3, 4, 5};
int largest = INT_MIN, second = INT_MIN;
for(int i = 0; i < n; i++)
{
if(arr[i] > largest)
{
second = largest;
largest = arr[i];
}
else if(arr[i] > second && arr[i] != largest)
{
second = arr[i];
}
}
printf("Largest: %d\nSecond: %d\n", largest, second);
}
Okay so here is the trick
When iterating through the array you have three cases.
The first case is that you have found a number greater than the largest number you have kept.
We attempt to initially keep the largest number at a minimum, hence the INT_MIN, so that any initial number that the array has will be within our scope. If we assume the initial largest number to be 0 then negative values wouldn't be considered at all and the program would fail if the array consisted of all negative numbers (an array with only 1 positive number would also fail since we also want the second largest).
If a greater number than the largest value is detected, we assign the largest value as the detected value. Since the former largest number is now the second-largest value we assign second to be largest. Hence
second = largest;
largest = arr[i];
The second case is that we have encountered a number that is not greater than the largest number that we currently hold but is greater than the second. Then we assign second to the said value hence:
second = arr[i];
The third case is that we have encountered a value that is neither larger than the larger nor larger than the second. We ignore the number if that is the case.
What is wrong with your code
The part that deals with the greatest number looks correct. However, the way that you set second to be arr[i] is wrong since i would be 10 here and arr[i] would be out of the bounds of the array. Also, you are iterating from 0 to 10 and checking arr[i-1] which is clearly unsafe.
this should work.
if(arr[1] > arr[0]){
greatest = arr[1];
second = arr[0];
}else{
greatest = arr[0];
second = arr[1];
}
for(int i=2;i<10;i++)
{
if(second < arr[i]){
if(greatest < arr[i]){
second = greatest;
greatest = arr[i];
}
else{
second = arr[i];
}
}
}
First I fill greatest and second with the first two entries of the array in the correct order.
Then I run, in a for-loop, from the 3rd (as i already sorted the first 2) to the 10th value and check for each entry:
if the value is greater than second and also greater than
greatest then this value is now the greatest value. thus the current
greatest value is now the 2nd greatest value.
if the value is greater than second and smaller than greatest then
this value is the 2nd greatest value. and the greatest value remains.
if the value is smaller than second it is neither the greatest nor
the 2nd greatest value.

what the function does? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
#define SIZE 10
void fun(int arr[]){
int i,k,j,n = SIZE;
k = 0;
for (i = 1 ; i < SIZE; i++) {
j = k;
while (j > 0 && arr[j] != arr[i])
j = j - 1;
if( j == 0){
k = k + 1;
arr[k] = arr[i];
}
else
n--;
}
}
This function was in my test today.
My question is: does someone know what it does?
What does the variable n represent at the end of the function?
At the end of the function, the variable n will have counted how many times each i-th array value in the range [0, SIZE) was unique among the first i array elements..
In addition, the first n elements of the array will contain exactly those elements that were found to be unique in the above sense. All other array entries will remain unchanged.
The other variables will have the following values:
i == SIZE
j == some value between [0, SIZE)
k == n-1
Some inline comments may help understand the code better.
#define SIZE 10
void fun(int arr[]){
int i,k,j,n = SIZE;
k = 0;
// walk through the array up until its 10th element, skipping
// the first entry and hoping that the array actually contains
// at least 10 entries
for (i = 1 ; i < SIZE; i++) {
// similar to i, the variable k also walks up towards 10.
// However it starts at 0, not at 1, and it does not
// necessarily get incremented in every loop iteration. More
// on that below.
// Here, we set the variable j to start out as the same value
// as the current k, but j will walk the opposite direction, i.e.,
// toward 0, not toward 10.
j = k;
// find the largest j in the open interval [0,k) for which
// the array entry arr[j] differs from the current arr[i]
while (j > 0 && arr[j] != arr[i])
j = j - 1;
// if no value in [0, k) was equal to arr[i], we'll end up \
// with j == 0
if( j == 0){
// then we increment k -- that is, k counts how many times
// we encountered a value arr[i] during the for-loop that was
// unique among the first i array entries. But since the
// for loop starts at 1 instead of 0, k will count one
// element too few.
k = k + 1;
// well, so much for 'unique': here, we actually copy the current
// value arr[i] into arr[k]
arr[k] = arr[i];
}
else
// this part in effect assures that the expression
// (n-k) gets decremented in every iteration of the loop,
// no matter if j == 0 is true or false.
// Since we start out with (n-k) = SIZE, and
// the loop body gets executed SIZE-1 times, (n-k) will
// be equal to 1 after the for-loop has terminated.
n--;
}
}

Need help on an algorithm (stack overflow) [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
This is a problem a friend of mine gave me as a challenge. I've managed to come up with a recursive algorithm that works fine for small inputs, however I get segmentation faults for large values. I suppose that's because of a stack overflow. I use the C language for solving the problem.
You are given an array of n numbers. Find and print the maximum length of the subset such that for any two numbers form that subset, the sum of the numbers is not divisible by k.
Input contains on the first line 2 numbers n and k, on the next line there are n numbers a[i] such that:
1 <= n <= 10^5
0 <= a[i] <= 10^9
1 <= k <= 100
# Example input:
4 3
1 7 4 2
# Output:
3
Explanation: (1 7 4) 1 + 7 = 8; 1 + 4 = 5; 7 + 4 = 11; all of them non-divisible by 3.
My solution is based on the following idea: For all numbers in the array check the sum with the others if it is divisible by k. If we find a match then create 2 arrays, one excluding the first term of the sum and one excluding the second one, this way we exclude such pairs from our subsets. Then do the same thing we did to the first array to both of them. If we have checked all the elements from the the array then set the solution to the length of the array and continue applying the "solver" to only the arrays that have a length greater than the solution already found. This algorithm works well for n < 47 , more than that and it gives me a seg fault. I would like to see any solution that solves the problem.
#include <stdio.h>
int n, k;
int * deleteElement(int * a, int n, int j){
int *c = (int*) malloc((n-1) * sizeof(int));
int k = 0;
for(int i = 0; i < n; i++){
if(i == j) continue;
c[k] = a[i];
k++;
}
return c;
}
int sol = 0;
void solver(int *a, int n, int *sol){
int *b, *c;
if(n <= *sol) return;
for(int i = 0; i < n-1; i++){
for(int j = i + 1; j < n; j++){
if((a[i] + a[j]) % k == 0){
c = deleteElement(a, n, i);
b = deleteElement(a, n, j);
solver(c, n-1, sol);
solver(b, n-1, sol);
return;
}
}
}
*sol = n;
}
int main(){
scanf("%d", &n);
scanf("%d", &k);
int a[n];
for(int i = 0; i < n; i++) scanf("%d", &a[i]);
solver(a, n, &sol);
printf("%d\n", sol);
return 0;
}
You could use iteration to get rid of one of your two recursive calls, but that wouldn't help with stack space, since they have the same depth -- one call is as bad as 2.
It's easy enough to write a completely iterative algorithm that actually tests all the valid sets, but that's still an exponential time algorithm. In any case that this would save you from a stack overflow, it would take way too long to run. Since that algorithm would also suck, I don't want to write it.
A reasonable linear-time way to solve this problem is:
Calculate a map MODCOUNTS where MODCOUNTS[m] = the number of elements x such that x%k == m
Since any valid subset can only have one element divisible by k, if MODCOUNTS[0] > 1, then set MODCOUNTS[0]=1
Similarly, if k is even, and MODCOUNTS[k/2] > 1, then set MODCOUNTS[k/2]=1
Now, add up all the values in MODCOUNTS, but leave out a value MODCOUNTS[i] if:
i > 0, i*2 < k, AND MODCOUNTS[i] < MODCOUNTS[k-i]; OR
i*2 > k AND MODCOUNTS[i] <= MODCOUNTS[k-i]
rule 4 reflects that fact that a valid subset cannot include any elements x and y such that (x+y)%k = 0, for the cases that we didn't take care of in rules 2 and 3. The biggest valid subset includes all the elements from in MODCOUNTS[i], or all the elements in MODCOUNTS[k-i], but not elements from both.
If you use sparse data structure like a hash table to implement MODCOUNTS, then the whole thing takes O(N) time.

Function in C that realize the mathematical union of two arrays of int in another one [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
The language is ANSI C. I have 2 arrays of int: A and B. A has an index called m and B an index called n. The assignment says that m MUST BE different from n, so the arrays must have different size. I have coded already this. A is ordered ascending while B is ordered descending. I have to write a function that does the mathematical union of the two arrays in another one called C. If an element is in both the arrays you have to put only one in the array of the union (array C).
My code does not work very well. The last element is not ordered, I receive an output with a very big last number that I do not know from where it comes.
int index_c=index_m+index_n; //the index of array c
// is obtained by the sum of two indexes of the array A and B
int c[index_c];
int k=0;
for (i=0; i < index_m; i++)
{
for (j=0; j < index_n; j++)
{
if (a[i]==b[j])
{
c[k]=a[i]; //put only one time if is repeated more time in the two arrays
}
else
{
c[k]=a[i]; //put the a[i] element in the array c
c[k+1]=b[j]; //the element of the other array next to
}
}
k++;
}
printf("Elements in array C are: \n");
for (i=0; i<index_c; i++)
printf("element %d\n", c[i]);
It doesn't matter if the array C is not sorted, I will sort after the union. Any suggestions?
I am trying the suggestion of put k++ when I add 1 input, and k+2 when I add two input to array C. Now It works a bit well, but it doesn't full work. I mean in output I have not big number values but one of the output value (the 3rd) is the same as the first.
Example: 3 9 3 2 5 The second 3 is wrong and it's missing a number that is covered by the second 3.
Other example 2 4 2 1 9
I spot two immediate logical errors which should be fixed at the very least:
you either store one number in c, when both inputs are the same, and increase k by 1, or you store two numbers into c. You should then increase k with 2 as well. In the code you have now, you only have to add another +1 -- but consider putting these additions inside the if..else test blocks for clarity. Currently, you are overwriting the last one stored.
You print the result from 0 to index_c, the sum of the lengths of the two input arrays. That is not logical because you are throwing out numbers. Hence you get 'random' numbers as output; those are merely uninitialized, i.e. never written to. Print from 0 to k, as that is the valid range of your input.
So far none of the answers exploit the fact that the arrays are both sorted. Here is an implementation which is almost identical to a merge as suggested in the comments. The complexity of the merge is O(m + n).
I have assumed that each array has no duplicates (no [0, 1, 1, 3]), but you could add checks like if (k == 0 || k > 0 && C[k - 1] != A[i]) to fix this if I assumed wrong.
The function returns the length of C.C is sorted in increasing order. To have C be sorted in decreasing order instead change if (A[i] < B[j]) to if (A[i] > B[j]).
int union_merge(const int *A, int m, const int *B, int n, int *C) {
int i = 0, j = n - 1, k = 0;
while (i < m && j >= 0) {
if (A[i] < B[j]) {
C[k++] = A[i++];
} else if (A[i] == B[j]) {
C[k++] = A[i++];
--j;
} else {
C[k++] = B[j--];
}
}
while (j >= 0) {
C[k++] = B[j--];
}
while (i < m) {
C[k++] = A[i++];
}
return k;
}
Let's say that you have two arrays A and B, and union array C. You can input both arrays A and B into one array. Then you can sort that array and after sorting iterate over array and add value to array C(union array) if you didn't already add that value.Total complexity is O( N * log(N) ) Look at code:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100000
int a[2*MAX+3], c[2*MAX+3];
int cmp(const void *a, const void *b) {
if ( *(int*)a < *(int*)b ) return -1;
if ( *(int*)a == *(int*)b ) return 0;
if ( *(int*)a > *(int*)b ) return 1;
}
int main() {
int i, k;
int n, m; scanf("%d%d", &n, &m); // size of the first array and size of the second array
n += m;
for(i = 0; i < n; ++i) // O(N) , input both arrays into one array
scanf("%d", &a[i]);
qsort(a, n, sizeof(int), cmp); // O( N * log(N) ), sort the given array
c[0] = a[0];
for(i = 1, k = 1; i < n; ++i) // O(N)
if(c[k - 1] != a[i]) // if the last element that you added to the union array is different than the current element in first array then add that element to union array
c[k++] = a[i];
for(i = 0; i < k; ++i) // O(K)
printf("%d ", c[i]);
return 0;
}

Iterate ALL the elements of a circular 2D array exactly once given a random starting element

We are given a 2-dimensional array A[n,m] with n rows and m columns and an element of that array chosen at random R.
Think of the array as being circular in that when we visit A[n-1, m-1] the next element we visit would be A[0, 0].
Starting with element R, we want to visit each element exactly once and call function foo() before moving to the next element.
The following is my first implementation but there is a bug. The bug being that if we start at row x somewhere between 0 and n-1, we will not visit element from 0 to x-1 in that column.
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
// Look at each column once
for (int i = 0; i < m; ++i)
{
for (; curr_row < n; ++curr_row)
{
foo(A[curr_row][curr_col]);
}
curr_row = 0;
curr_col = (curr_col + 1) % m;
}
What is a clean way to do this traversal such that we meet the above requirements?
Just move to the next index, and check whether you are back at the start, in which case, stop:
// should be something that guarantees in-range indices
curr_row = rand();
curr_col = rand();
int i = curr_row, j = curr_col;
do {
foo(A[i][j]);
++j;
if (j == n) {
j = 0;
++i;
if (i == m) {
i = 0;
}
}
}while(i != curr_row || j != curr_col);
This doesn't do what your implementation does, but what the question title asks for.
quite rusty with c , but it should be the same:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
//first row
for(int j=curr_col;j<m;++j)
foo(A[curr_row][j]);
//rest of the rows
for(int i=(curr_row+1)%n;i!=curr_row;i=(i+1)%n)
for(int j=0;j<m;++j)
foo(A[i][j]);
//first row , going over missed cells
for(int j=0;j<curr_col;++j)
foo(A[curr_row][j]);
if you care a lot about performance , you can also divide the second loop so that there won't be a "%" at all .
another alternative , since C has 2d arrays in a simple array:
// Init - pretend rand() always returns valid index in range
curr_row = rand();
curr_col = rand();
int start=curr_row*m+curr_col;
int maxCell=n*m;
int end=(start-1)%maxCell;
for(int i=start;i!=end;i=(i+1)%maxCell)
foo(A[i]);
foo(A[end]);
could have a tiny math bug here and there ,but the idea is ok.
A[curr_row, curr_col] is not the syntax used to access a member of a multidimensional array; instead, you want A[curr_row][curr_col], assuming the array was declared correctly. A[curr_row, curr_col] will invoke the comma operator, which effectively computes the first value, then throws it away and calculates the second value, then indexes the array with that value.

Resources