Stuck on code about arrays and moving digits in it - c

There are two arrays:
s: 7 3 6 2 8
c: 0 12 5 23 14
new array: 8 3 7 6 2
Basically, you look at array c and if it has an even number, you print the one from the array s. For example, 14 is even so you print 8. You need to print them in that order, from right to left.
So I read the first two arrays, but I don't know how to put the rest of the code. If you put:
array s: 1 2 3
array c: 4 4 4
you will get: 3 2 1, which we need, but if I put 1 odd number, I will get some error number. I don't know how to put the rest of array s, after I put the even numbers.
for(d=0; d<ns; d++)
{
scanf("%d", &s[d]); //here we have the first array
}
for(d=0; d<nc; d++)
{
scanf("%d", &c[d]); //second array
}
for(d=0; d<ns; d++)
{
if(c[d]%2==0) //I check here if the nb. from second array are even
{
r[d]=s[d]; //I try to put the numbers from the first array
}
}
for(d=ns-1; d>-1; d--)
{
printf("%d ", r[d]); //I print the new array
}
}

Your problem description is not very clear, but you want to do this:
You have two arrays s and c of the same size N.
First, walk through the array backwards. If the value in c is even, add the corresponding value from s to the result array.
Finally, add the remaining elements of s to the array. The result array will now have N elements, too.
The first thing to notice is that if you look at c[4] and decide to add element s[4] to the result array, the index for that array is 0, because you add elements from the front. In general, if you want to append to an array, you do:
int array[5]; // space for 5 ints
int n = 0; // current length; start with empty array
array[n++] = 5; // array == [5]; n == 1
array[n++] = 8; // array == [5, 8]; n == 2
array[n++] = 15; // array == [5, 8, 15]; n == 3
Your backwards loop works, but it is a bit clumsy, in my opinion. In C (and other languages), ranges are described by the inclusive lower bound and an exclusive upper bound. In the range [0, N), the value N is just out of bound.
Forwad loops initialize to the lower bound, break on the upper bound and increment after each cycle. Because of this asymetry, backwards loops are simpler when you start with the upper bound, break on the lower bound, but decrement at the start of the loop:
for (i = N; i-- > 0; ) ...
The empty update section looks strange, but in this loop, the index never leaves the valid range and therefore also works with unsigned integers.
Create your arrays:
int s[N] = {7, 3, 6, 2, 8}; // value array
int c[N] = {0, 12, 5, 23, 14}; // control array
int r[N]; // result array
int k = 0; // length of r
Now walk the arrays backwards and pick the items you want:
for (i = N; i-- > 0; ) {
if (c[i] % 2 == 0) {
r[k++] = s[i];
}
}
Walk the array forwards and pick the items you didn't pick in the first pass:
for (i = 0; i < N; i++) {
if (c[i] % 2) {
r[k++] = s[i];
}
}
VoilĂ .

Related

Speeding up the process to find elements which are divisible by elements of the same array

I came across a problem:
Given an array, find the max count of this array, where count for an element in the array is defined as the no. of elements from this array which can divide this element.
Example: max count from the array [2,2,2,5,6,8,9,9] is 4 as 6 or 8 can be divided by 2,2,2 and by themselves.
My approach is:
Sort the array.
Make a set from this array (in a way such that even this set is sorted in non-descending order).
Take another array in which the array indices are initialized to the no. of times an element appears in the original array. Example: in above example element '2' comes three times, hence index '2-1' in this new array will be initialized to 3, index '9-1' will be initialized to 2 as '9' comes 2 times in this array.
Using two loops I am checking the divisibility of largest (moving largest to smallest) element in the set with smallest (moving smallest to largest) element of the set.
Conditions
1 <= arr[i] <= 10000
1 <= i <= 10000
#include <stdio.h>
#include <stdlib.h>
#include<limits.h>
int cmp(const void *a, const void *b)
{
return (*(int*)a - *(int*)b);
}
void arr_2_set(int *arr, int arr_size,int *set, int *len)
{
int index = 0;
int set_len = 0;
int ele = INT_MIN;
qsort(arr,arr_size,sizeof(int),cmp);
while(index < arr_size)
{
if(ele != arr[index])
{
ele = arr[index];
set[set_len] = ele;
set_len++;
}
index++;
}
*len = set_len;
}
int main(void)
{
int arr[]={2,2,2,5,6,8,9,9}; //array is already sorted in this case
int size = sizeof(arr)/sizeof(arr[0]);
int set[size];
int index = 0;
int set_len = 0;
arr_2_set(arr, size, set, &set_len); //convert array to set - "set_len" is actual length of set
int rev = set_len-1; //this will point to the largest element of set and move towards smaller element
int a[100000] = {[0 ... 99999] = 0}; //new array for keeping the count
while(index<size)
{
a[arr[index] -1]++;
index++;
}
int half;
int max=INT_MIN;
printf("set len =%d\n\n",set_len);
for(;rev>=0;rev--)
{
index = 0;
half = set[rev]/2;
while(set[index] <= half)
{
if(set[rev]%set[index] == 0)
{
a[set[rev] -1] += a[set[index]-1]; //if there are 3 twos, then 3 should be added to count of 8
//printf("index =%d rev =%d set[index] =%d set[rev] =%d count = %d\n",index,rev,set[index],set[rev],a[set[rev] -1]);
}
if(max < a[set[rev]-1])
max = a[set[rev]-1];
index++;
}
}
printf("%d",max);
return 0;
}
Now my question is how can I speed up this program? I was able to pass 9/10 test cases - for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
For creating a set and finding the count - use a single while loop, when the size of array is big then using a single loop will matter a lot.
In the later half section where two nested loops are there - don't go from largest to smallest element. Go from smallest to largest element while checking which largest element with index lower than the current element can divide this element, add the count of that element to the current element's count (using set[i]/2 logic will still hold here). This way you'll avoid a lot of divisions. Example: if set is {2,3,4,8} in this case, lets say your current position is 8 then you go down till largest element smaller than or equal to 8 which can divide 8 and add it's count to current element's (8) count.
for the 10th test case (which was hidden), it was showing "Time Limit Exceeded".
That may suggest a more time efficient algorithm is expected.
The posted one, first sorts the array (using qsort) and then copies only the unique values into another array, set.
Given the constraints on the possible values, it may be cheaper to implement a counting sort algorithm.
The last part, which searches the maximum number of dividends, can then be implemented as a sieve, using an additional array.
#include <stdio.h>
enum constraints {
MAX_VALUE = 10000
};
int count_dividends(size_t n, int const *arr)
{
// The actual maximum value in the array will be used as a limit.
int maxv = 0;
int counts[MAX_VALUE + 1] = {0};
for (size_t i = 0; i < n; ++i)
{
if ( counts[arr[i]] == 0 && arr[i] > maxv )
{
maxv = arr[i];
}
++counts[arr[i]];
}
// Now, instead of searching for the dividends of an element, it
// adds the number of factors to each multiple.
// So, say there are two elements of value 3, it adds 2 to all
// the multiples of 3 in the total array.
int totals[MAX_VALUE + 1] = {0};
int count = 0;
// It starts from 2, it will add the numbers of 1's once, at the end.
for (int i = 2; i <= maxv; ++i)
{
// It always skips the values that weren't in the original array.
if ( counts[i] != 0 )
{
for ( int j = 2 * i; j <= maxv; j += i)
{
if ( counts[j] != 0 )
totals[j] += counts[i];
}
if ( counts[i] + totals[i] > count )
{
count = counts[i] + totals[i];
}
}
}
return count + counts[1];
}
int main(void)
{
{
int a[] = {2, 4, 5, 1, 1, 6, 14, 8, 2, 12, 1, 13, 10, 2, 8, 5, 9, 1};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 10, because of 1 1 1 1 2 2 2 4 8 8
printf("%d\n", count_dividends(n, a));
}
{
int a[] = {2, 4, 5, 2, 7, 10, 9, 8, 2, 4, 4, 6, 5, 8, 4, 7, 6};
size_t n = (sizeof a) / (sizeof *a);
// Expected: 9, because of 2 2 2 4 4 4 4 8 8
printf("%d\n", count_dividends(n, a));
}
}

First number in array not transferring to new array correctly

I am writing a program to break numbers in an array into their digits then store those digits in a new array. I have two problems:
It does not display the first number in the array (2) when transferred to the second array, and I am not entirely sure why.
The array may contain 0's, which would break my current for loop. Is there another way to implement a for loop to only run for as many numbers are stored in a array without knowing how big the array is?
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Setting an array equal to test variables
int sum[50] = { 2, 6, 3, 10, 32, 64 };
int i, l, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of separate variable k every time loop runs
for (i = 0; sum[i] > 0; i++ && k++)
{
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for (l = 0; l < dig; l++)
{
printf("%i\n", sumdig[l]);
}
}
This is the output:
6
3
0
1
2
3
4
6
0
Solution:
It does not display the first number in the array (2) when transferred to the second array
changes i++ && k++ into i++,k++
Is there another way to implement a for loop to only run for as many numbers are stored in an array
There are many different ways but here is some to illustrate it in a few different scenarios:
1. The array length is known and fixed:
Let the compiler automatically allocate the array for you. And then for(i=0; i<6; i++)
2. Able to calc the array length:
Then count the number of elements when initializing the array into a varible. Then just for(i=0; i<SizeCount; i++)
3. Not-able to know array size for some reason:
It is rare but, in that case, you can pre-set a stop criteria i.e. -1 or some other flag so that you can stop when it reaches the terminator i.e. set or pre-set all other values of sum to be -1. Then you can while(sum[i] != -1) This is how string lengths work in C, either with NULL termination (string end with the number 0 or value NULL) or, with input, the line break character \n indicating a termination.
DEMO
Here is a demo of full code with some explanation:
#include <stdio.h>
int main(void){
int sum[] = {2, 6, 3, 10, 32, 64}; // compiler is smart enough know the size
int i, k = 0, sumdig[10], dig = 0;
// Runs for every digit in array sum, increases size of seperate variable k everytime loop runs
for(i = 0; i < sizeof(sum)/sizeof(int); i++, k++){
sumdig[k] = sum[i] % 10;
dig++;
sum[i] /= 10;
// If statement checks to see if the number was two digits
if (sum[i] > 0)
{
// Advancing a place in the array
k++;
// Setting the new array position equal to the
sumdig[k] = sum[i] % 10;
dig++;
}
}
// For testing purposes - looking to see what digits have been stored
for(i = 0; i < dig; i++){
printf("%i\n", sumdig[i]);
}
}
Compile and run
gcc -Wall demo.c -o demo
./demo
Output
2
6
3
0
1
2
3
4
6

Why unintialized array elements are not 0 always in C

I input 4566371 and find out that uninitialized array elements are not 0 as said in our texts
#include <stdio.h>
#define MAX 10
// Function to print the digit of
// number N
void printDigit(long long int N)
{
// To store the digit
// of the number N
int array_unsorted[MAX];//array_unsorteday for storing the digits
int i = 0;//initializing the loop for the first element of array_unsorted[]
int j, r;
// Till N becomes 0,we will MOD the Number N
while (N != 0) {
// Extract the right-most digit of N
r = N % 10;
// Put the digit in array_unsorted's i th element
array_unsorted[i] = r;
i++;
// Update N to N/10 to extract
// next last digit
N = N / 10;
}
// Print the digit of N by traversing
// array_unsorted[] reverse
for (j =MAX; j >=0; j--)
{
printf("%d ", array_unsorted[j]);
}
}
// Driver Code
int main()
{
long long int N;
printf("Enter your number:");
scanf("%lld",&N);
printDigit(N);
return 0;
}
output:
Enter your number:4566371
77 0 8 32765 4 5 6 6 3 7 1
Process returned 0 (0x0) execution time : 2.406 s
Press any key to continue.
The other values should be o right?Why 77,0,32765 this way?Why not all are 0?like 0 0 0 0 4 5 6 6 3 7 1?
An array of integers declared inside a function has indeterminate values if it is uninitialized. If a similar array is declared at global scope, outside all functions, it will be initialized with zeros by default.
To make an array that is always initialized to zeros, do this:
int array_unsorted[MAX] = {0};
This works because in C, = {0} will initialize all values with zero. If you say = {10, 20} it will initialize the first two elements as written, and the rest to zero.
You have correctly reserved a memory space for your array array_unsorted but the memory has not been cleaned before use. This memory reserved it was probably used by another function or variable before yours! This is why it already has some values in it. You should set it to 0 manually before starting to use it.
As noted in other answers, you may want to initialize your integer array. Whether or not you do that, you might want to replace the for loop statement conditions of:
for (j =MAX; j >=0; j--)
with:
for (j = i - 1; j >=0; j--) /* Start at the place the digit storage ended */
That way, you are not moving into array elements that were not used in the digit storage portion of your function.
Regards.

Sorting out Array of several integers, numbers in array seems to have shifted by 1

I'm trying to solve a question to find the lowest and highest numbers in an array in C Language. I tried swapping the numbers that are close to each other to align the numbers from small(left) to big(right).
For example, if the array is 20, 10, 35, 30, 7, first compare 20 and 10, if 20 is larger than 10, swap the numbers to 10, 20. then compare 20 and 35, 20 is smaller than 35, so go on. then compare 35 and 30, 35 is bigger than 30, swap numbers to 30, 35. then compare 35 and 7, 35 is bigger than 7, swap numbers to 7, 35.
Did these 'swappings' again 3 more times to align the numbers perfectly.
After I've done the swappings, I just printed the first array number and the last array number, but the numbers aren't correct, and it looks like the numbers have shifted by 1. For example, if I align the above array, it is 7[0], 10[1], 20[2], 30[3], 35[4]. (marked the indices by []) So, when I print the indice[0], and indice[4], I expected the numbers to show 7 and 35.
But in fact I have to print indice[1], and indice[5] to get the numbers 7 and 35 to be printed. The numbers seem to have shifted by 1..
I really want to know why the numbers have shifted by 1 in the array.
Thank you for reviewing the question.
I'll also post the original question that I'm trying to solve.
"Q. Input the number N first to decide how much numbers to enter, then input the N-numbers. Print the lowest and highest number in the N-numbers you have input."
And here's my code:
#include<stdio.h>
#pragma warning(disable:4996)
int main(void)
{
int input, i, j, temp, k;
int value[100] = { 0 };
scanf("%d", &input);
for (i = 0; i < input; i++)
{
scanf("%d", &value[i]);
}
for (k = 0; k < input; k++)
{
for (j = 0; j < input; j++)
{
if (value[j] > value[j + 1])
{
temp = value[j + 1];
value[j + 1] = value[j];
value[j] = temp;
}
}
}
printf("%d %d\n", value[0], value[input-1]);
return 0;
}
Because you're iterating over the whole array, value[j+1] walks off the end of the user's input. Since value was initialized 0 to, temp = value[j + 1] will be 0. So 0 will always be your min (unless the user enters negatives).
Instead, iterate only up to j < input - 1.
I'm trying to solve a question to find the lowest and highest numbers in an array in C Language.
You don't need to sort the array, you can do this in a single pass.
// Initialize min and max to be the first value.
int min = value[0];
int max = value[0];
// Then loop through the rest of the array checking if each value is
// smaller than min and/or larger than max.
for (i = 1; i < input; i++) {
if( value[i] < min ) {
min = value[i];
}
if( value[i] > max ) {
max = value[i];
}
}
printf("min: %d, max: %d\n", min, max);
Note: It's not necessary to declare all your variables up front. You can declare them as you need them. And you don't need different iterators for each loop, you can reuse i as I have above.

In this bubble sort code what do these variables c & d mean in C?

So I understand that an ascending order bubble sort checks if index i is greater than index "i + 1", and if it is, then it swaps the positions, and then keeps going till it reaches the end of the loop, and then the loop starts over, and keeps switching positions, until every index "i" is not greater than "i + 1", and then you loop is sorted in ascending order completely.
So I'm looking at this bubble sort code.
Here is the source: www.programmingsimplified.com/c/source-code/c-program-bubble-sort
Here is the code:
/* Bubble sort code */
#include <stdio.h>
int main()
{
int array[100], n, c, d, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
printf("Sorted list in ascending order:\n");
for ( c = 0 ; c < n ; c++ )
printf("%d\n", array[c]);
return 0;
}
I understand all variables except "d". I have no clue what they mean esoterically. So this is the section of code that confuses me:
for (c = 0 ; c < ( n - 1 ); c++)
{
for (d = 0 ; d < n - c - 1; d++)
{
if (array[d] > array[d+1]) /* For decreasing order use < */
{
swap = array[d];
array[d] = array[d+1];
array[d+1] = swap;
}
}
}
As I understand it, the first for loop steps through the array of length n - 1 because in C the first index of an array is 0. The length of the second for loop appears to be the length of "c" as it steps through the array, but it's not the length of the array (n - 1), so that confuses me. I don't get what d is, so I don't get why "d" is used in the swap statements instead of "c. I totally get what the swap does though, switching the elements of the array as I explained in the intro with swapping the indices.
So I guess what I don't understand the most is why the second for loop is necessary and the length of the array of d:
for (d = 0 ; d < n - c - 1; d++)
{
// if comparison switch check.
}
So the code provided in the website does a bubble sort correctly.
I tried it with n = 5, and values = {9, 8, 7, 6, 5}
It successfully rearranges them to {5, 6, 7, 8 , 9} in ascending order.
Since I don't understand the second for loop, I thought I would see what would happen if I did not include it, and the result is interesting. I just changed removed the second for loop, and replaced mentions of "d" with c.
#include <stdio.h>
int main(void)
{
int array[100], n, c, swap;
printf("Enter number of elements\n");
scanf("%d", &n);
// Tell the user to enter integers in a loop.
printf("Enter %d integers\n", n);
for (c = 0; c < n; c++)
scanf("%d", &array[c]);
for(c = 0; c < (n - 1); c++)
{
if(array[c] > array[c + 1])
{
swap = array[c];
array[c] = array[c+1];
array[c+1] = swap;
}
}
printf("Sorted list in ascending order:\n");
for(c = 0; c < n; c++)
printf("%d\n", array[c]);
return (0);
}
If I see what happens with this code when I removed the second for-loop I get this result. I input 5 elements: {9, 8, 7, 6, 5}, and the order I get back is this: {8, 7, 6, 5, 9}. This is clearly not correct ascending order. But it did a bubble sort through the whole set; it just only completed one pass, so that is why this sorted array starts at 8 because it only made one pass.
Again, this incorrect code now can actually correctly sort this 5 element array: {1, 8, 2, 3, 7}. It changes it to {1, 2, 3, 7, 8}. But it only took one pass through the array to correctly complete this bubble sort.
So I have discovered that the second for loop makes sure the array is numerically sorted in increasing order correctly as many number of passes of bubble sorts are required to make the change.
But I still don't understand it, and it's hard to explain how I don't understand it. I very well know that "c" is the index that slides through the array from beginning to end. But what kind of index is "d" and where does it truly start from, and where does it really end?
Thanks.
If you happen to have simpler code that doesn't require a for-loop inception for a bubble sort, and you can only use one variable, then I would appreciate admiring that code.
Here c & d using to traverse and sorting the loop
for c
the whole loop is traversing n times
and for d
all elements of the array except the sorted are being traversed and operated for sorting the array
hope that you understand the fact now
Happy Coding
What happens is when C is 0 we traverse the whole array (up to N - C - 1) and the maximum digit gets put at the end. Once we have the biggest digit at the end of the array where it belongs, well, we don't need to worry about it anymore. So after that, C increments, and we sort up N - 1 - 1, which will be the farthest value that D will go up to.
Another way to explain. When C is 0, we bring the maximum digit up to last position in the array. When C is 1, we bring up the 2nd biggest digit up to the last - 1 position in the array. And so on and so forth.
D is the one that actually does the traversing, and think of C as a counter.

Resources