Write a program that reads integer from the keyboard and, on the output, writes the sum of the divisors of n (other than itself).
I've created a method that finds the sum of divisor. Using the while statement I can have up to 10 integers entered by the user until EOF. In the while statement I had sum = the output of sum_divisor and print out sum.
If I enter 0 0 0 4 5 6 12 then the output should be 0 0 0 3 1 6 16.
The output I get is 0 0 0 3 4 10 26. How can I make it so that it doesn't add the sum_divisor to the previous sum?
#include <stdio.h>
int sum_divisor(int x);
int main()
{
int x;
int sum;
printf("Enter up to 10 positive integer ending with EOF:\n");
while((scanf("%d",&x)) != EOF){
sum = sum_divisor(x);
printf("%d ", sum);
}
return 0;
}
int sum_divisor(int x){
int i;
int sum;
if(x<= 0){
sum = 0;
}
else{
for(i=1;i<x;++i)
{
if(x%i==0)
sum += i;
}
}
return sum;
}
You should initialise sum to zero within your function. Otherwise, it will be set to some arbitrary value and the else block will have an arbitrary result.
In other words, change:
int sum;
into:
int sum = 0;
Of course, once you've done that, there's no need to explicitly do anything for the case where x is less than one. In addition, the initial if is superfluous since the for body won't execute when x is less than one, so you could get away with something like:
int sumDivisors (int x) {
int i, sum = 0;
for (i = 1 ; i < x; i++) {
if ((x % i) == 0) {
sum += i;
}
}
return sum;
}
As an aside, the values you're actually seeing without the initialisation are accumulating:
0 -> 0
0 -> 0
0 -> 0
3 -> 3
1 -> 4
6 -> 10
16 -> 26
This is almost certainly because each call to the function is reusing the same memory for the stack frame, including the variable sum, so sum is simply being added to each time (that the passed-in parameter is greater than one).
However, that's simply an artifact of the implementation, it's not guaranteed by the standard, which states quite clearly in C11 6.7.9 Initialization /10:
If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate.
In other words, don't rely on this.
And, as yet another aside, it's a mathematical given that, if a number n divides evenly by a, it also divides evenly by n/a. You can use this to your advantage to possibly make the code a little more efficient (though, as with all optimisations, you should measure, not guess).
Since you're discounting the number itself as a divisor, you have to treat the divisor 1 as a special case. You also have to treat perfect squares as a special case so that you don't add the square root twice.
The following code would be a good starting point for that:
int sumDivisors (int x) {
int i, sum;
// Always return zero for -inf..1 inclusive.
if (x < 2)
return 0;
// Otherwise, 1 is factor, search for others
// up to but NOT including sqrt(x).
for (i = 2, sum = 1 ; i * i < x; i++) {
if ((x % i) == 0) {
sum += i;
sum += x / i;
}
}
// Add in sqrt(x) ONCE for a perfect square.
if (i * i == x)
sum += i;
return sum;
}
When you call sum_divisor inside the while statement the same block of stack is being allocated, and therefore the sum variable is allocated in the same position on every call. At the first call the value is 0,(but not necessarily), the next time the value will be the one you calculated on the previous call.
int sum = 0; should fix it.
int sum_divisor(int x){
if(x <= 0) { // you do not need to even alocate space for i an sum if x < 1.
return 0;
}
int i = 1;
int sum = 0;
for(i=1;i<x;++i)
{
if(x%i==0)
sum += i;
}
return sum;
}
Related
Given below is the code for finding prime numbers between the interval entered by the user.
#include <stdio.h>
int main() {
int n1, n2, i, flag;
scanf("%d%d", &n1, &n2);
for (i = n1; i <= n2; i++) {
flag = prime(i);
if (flag == 1)
printf("\n%d", i);
}
return 0;
}
int prime(int n) {
int j, flag = 1;
for (j = 2; j <= n / 2; j++) {
if (n % j == 0) {
flag = 0;
break;
}
}
return flag;
}
Can anyone explain me how this code deals with odd number, which are not prime (for ex: 15, 21, 25, etc)
int prime(int n) {
int j, flag = 1;
for (j = 2; j <= n / 2; j++) {
if (n % j == 0) {
flag = 0;
break;
}
}
return flag;
}
See in this prime function, when we observe the iteration of for loop if value of n is 15 then it will look like this:
for (j = 2; j <= 15 / 2; j++)
I agree this is true. Because 2<7.
Since the condition is true we will enter inside the for loop:
if(n%j==0){
flag=0;
break;
}
Now, since n=15 and j=2, value of n%j=1, which is obviously not equals to 0; so if loop will not be executed and the prime function will return flag =1; and the main function will print 15 as a prime.
But, after Executing the program the code is showing the correct results: it's not showing 15 as a prime.
So can anyone please help me understand the logic behind this code? (Actually I want to understand how this code is eliminating non-prime odd numbers.)
You checked the execution for j==2, but since there is a for loop for(j=2;j<=n/2;j++). The code will run from j=2 to j=n/2. So, if you consider all the iterations, you will realize that the function is working fine.
The first if statement is false, so for j==2, the program won't go inside the if statement.
The loop will iterate for the next value of j, which is 3. Since 15%3 == 0, the program will execute the statements within the if statement and return that 15 is not a prime number.
for(j=2;j<=n/2;j++){
if(n%j==0){
flag=0;
break;
}
}
In the case of n=15, the loop starts at i=2, the test i<=n/2 is true because 2<=7, then 15%2 is 1, hence the loop proceeds and i is incremented to 3, the loop test is true again because 3<=7 but 15%3 is 0 so flag is set to 0 and returned.
Note these remarks:
the code does not have a recursive function. You merely call a function prime() to check each number in the interval for primality.
prime() should be defined or at least declared before the main() function that calls it.
you can test the return value of prime(i) directly. No need for a flag variable.
for prime numbers, the loop will iterate way too far: you can change the test to j <= n / j to stop at the square root of n.
you can return directly from the loop body.
you should output the newline after the number.
Here is a modified version:
#include <stdio.h>
int isprime(int n) {
int j;
for (j = 2; j <= n / j; j++) {
if (n % j == 0)
return 0;
}
return 1;
}
int main() {
int n1, n2, i;
if (scanf("%d%d", &n1, &n2) != 2)
return 1;
for (i = n1; i <= n2; i++) {
if (isprime(i))
printf("%d\n", i);
}
return 0;
}
Can anyone explain me how this code deals with odd number, which are not prime (for ex: 15, 21, 25, etc)
int prime(int n) {
int j, flag = 1;
for (j = 2; j <= n / 2; j++) {
if (n % j == 0) {
flag = 0;
break;
}
}
return flag;
}
Well this function doesn't need to handle specially nonprime numbers, based on the fact that if we can divide the number n by something (be prime or not), the number will be compose. What it does it to get out of the loop (with flag changed into 0) as soon as it finds a number j that divides n.
There's an extra optimization, that can save you a lot of time, that consists on calculating numbers until the integer rounded down square root of n as, if you can divide the number by a number that is greater than the square root, for sure there will be a number that is less than the square root that also divides n (the result of dividing the original number by the first will give you a number that is lower than the square root) so you only need to go up until the square root. While calculating the square root can be tedious (there's a library function, but let's go on), it is only done once, so it is a good point to use it. Also, you can initialy try dividing the number by two, and then skip all the even numbers, by adding 2 to j, instead of incrementing.
#include <math.h>
/* ... */
int prime(unsigned n) {
/* check for special cases */
if (n >= 1 && n <= 3) return TRUE; /* all these numbers are prime */
if (n % 2 == 0) return FALSE; /* all these numbers are not */
/* calculate (only once) the rounded down integer square root */
int j, square_root = isqrt(n); /* see below */
for (j = 3; j <= square_root; j += 2) { /* go two by two */
if (n % j == 0)
return FALSE;
}
/* if we reach here, all tests failed, so the number must be prime */
return TRUE;
}
While there's a sqrt() function in <math.h>, I recommend you to write an integer version of the square root routine (you can devise it easily) so you don't need to calculate it in full precision (just to integer precision).
/* the idea of this algorithm is that we have two numbers between 1 and n,
* the greater being the arithmetic mean between the previous two, while
* the lower is the result of dividing the original n by the arithmetic mean.
* it is sure than if we select the arithmetic mean, the number will be
* between the previous ones, and if I divide n by a number that is lower,
* the quotient will be higher than the original number. By the way, the
* arithmetic mean is always bigger than the square root, so the quotient
* will be smaller. At each step, both numbers are closer to each other, and
* so, the smaller is closer to the result of dividing n by itself (and this
* is the square root!)
*/
unsigned isqrt(unsigned n)
{
unsigned geom = 1, arith = n;
while (geom < arith) {
arith = (geom + arith) / 2;
geom = n / arith;
}
/* return the smaller of the two */
return arith;
}
so, your program would be:
#include <stdio.h>
#define FALSE (0)
#define TRUE (!FALSE)
unsigned isqrt(unsigned n)
{
unsigned geom = 1, arith = n;
while (geom < arith) {
arith = (geom + arith) / 2;
geom = n / arith;
}
return arith;
}
int prime(unsigned n) {
/* check for special cases */
if (n >= 1 && n <= 3) return TRUE;
if (n % 2 == 0) return FALSE;
/* calculate (only once) the rounded down integer square root */
int j, square_root = isqrt(n);
for (j = 3; j <= square_root; j += 2) {
if (n % j == 0) {
return FALSE;
}
}
return TRUE;
}
int main() {
unsigned n1, n2, i;
scanf("%u%u", &n1, &n2);
for (i = n1; i <= n2; i++) {
if (prime(i))
printf("%u\n", i);
}
return 0;
}
If you try your version against this one, with values like 2000000000 and 2000000100 you will see how this is saving a lot of calculations (indeed, for the cases below, the case of considering only the odd numbers when going throug the loop will take out of it half the numbers ---this is 1000000000 tests---, but the square root will reduce the number of tests to its square root ---only around 40000 tests--- for each number!!!).
$ primes
2000000000 2000000100
2000000011
2000000033
2000000063
2000000087
2000000089
2000000099
$ _
Your version takes (on my system) this execution time:
$ echo 2000000000 2000100000 | time primes0 >/dev/null
3.09user 0.00system 0:03.09elapsed 99%CPU (0avgtext+0avgdata 1468maxresident)k
0inputs+0outputs (0major+69minor)pagefaults 0swaps
$ _
while the version proposed takes:
$ echo 2000000000 2000100000 | time primes >/dev/null
0.78user 0.00system 0:00.78elapsed 99%CPU (0avgtext+0avgdata 1572maxresident)k
0inputs+0outputs (0major+72minor)pagefaults 0swaps
$ _
Write a function getNumberOfSquares(int n) (C) / get_number_of_squares that will return how many integer (starting from 1, 2...) numbers raised to power of 2 and then summed up are less than some number given as a parameter.
e.g 1: For n = 6 result should be 2 because 1^2 + 2^2 = 1 + 4 = 5 and 5 < 6 E.g 2: For n = 15 result should be 3 because 1^2 + 2^2 + 3^2 = 1 + 4 + 9 = 14 and 14 < 15
For the function above I wrote a program but the test program gave an error that is when input is getNumberOfSquares(100000) function should return 66 but mine returns 403.
Here is my solution:
int getNumberOfSquares(int n){
int sum=0;
int limit=0;
for (int i = 1; i < n && n>sum; ++i)
{
sum += i*i;
++limit;
if(sum>=n){
sum -= i*i;
--limit;
}
}
return limit;
}
Assuming that an integer is 32 bits on your system, i*i will overflow once it reaches a value of 65536. That causes the inaccuracies.
However it shouldn't actually reach that point, since you continue to check values of i even after the value of sum exceeds n. You should break out of the loop when you reach that point.
int getNumberOfSquares(int n){
int sum=0;
int limit=0;
for (int i = 1; i < n; ++i)
{
if (sum + i*i >= n) {
return limit;
}
sum += i*i;
++limit;
}
return limit;
}
You want to find the biggest i such that sum < n. So this should be the only condition breaking the loop. You don't need to check even that i < n.
Now the problem of your code is that you modify sum when it gets big enough to break the loop, making it again less than n. So if sum < n was your only condition you would have had an infinite loop. But since you have the i < n condition, the program keep adding and subtracting i*i to sum until i < n.
If n is small enough, adding and subtracting i*i doesn't change sum and when the loop breaks you get your result.
But if i can grow big enough to make sum greater than the greatest int you can have, sum overflows and becomes a meaningless value.
The solution is to eliminate the condition if(sum>=n){}.
Removing the condition will reveal that limit is like i, so you can even use i as returned value.
And keeping in mind that you don't need the condition i < n, your function becomes
int getNumberOfSquares(int n) {
int i, sum = 0;
for(i = 1; sum < n; ++i) {
sum += i*i;
}
return i-2;
}
Returning i-2 because the i making sum > n was already 1 more than the value you wanted to return and then before sum > n is checked, thefor increments i.
I am new to programming and C is the only language I know. Read a few answers for the same question written in other programming languages. I have written some code for the same but I only get a few test cases correct (4 to be precise). How do I edit my code to get accepted?
I have tried comparing one element of the array with the rest and then I remove the element (which is being compared with the initial) if their sum is divisible by k and then this continues until there are two elements in the array where their sum is divisible by k. Here is the link to the question:
https://www.hackerrank.com/challenges/non-divisible-subset/problem
#include<stdio.h>
#include<stdlib.h>
void remove_element(int array[],int position,long int *n){
int i;
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
*n=*n-1;
}
int main(){
int k;
long int n;
scanf("%ld",&n);
scanf("%d",&k);
int *array=malloc(n*sizeof(int));
int i,j;
for(i=0;i<n;i++)
scanf("%d",&array[i]);
for(i=n-1;i>=0;i--){
int counter=0;
for(j=n-1;j>=0;j--){
if((i!=j)&&(array[i]+array[j])%k==0)
{
remove_element(array,j,&n);
j--;
continue;
}
else if((i!=j)&&(array[i]+array[j])%k!=0){
counter++;
}
}
if(counter==n-1){
printf("%ld",n);
break;
}
}
return 0;
}
I only get about 4 test cases right from 20 test cases.
What Gerhardh in his comment hinted at is that
for(i=position;i<=(*n)-1;i++){
array[i]=array[i+1];
}
reads from array[*n] when i = *n-1, overrunning the array. Change that to
for (i=position; i<*n-1; i++)
array[i]=array[i+1];
Additionally, you have
remove_element(array,j,&n);
j--;
- but j will be decremented when continuing the for loop, so decrementing it here is one time too many, while adjustment of i is necessary, since remove_element() shifted array[i] one position to the left, so change j-- to i--.
Furthermore, the condition
if(counter==n-1){
printf("%ld",n);
break;
}
makes just no sense; remove that block and place printf("%ld\n", n); before the return 0;.
To solve this efficiently, you have to realize several things:
Two positive integer numbers a and b are divisible by k (also positive integer number) if ((a%k) + (b%k))%k = 0. That means, that either ((a%k) + (b%k)) = 0 (1) or ((a%k) + (b%k)) = k (2).
Case (1) ((a%k) + (b%k)) = 0 is possible only if both a and b are multiples of k or a%k=0 and b%k=0. For case (2) , there are at most k/2 possible pairs. So, our task is to pick elements that don't fall in case 1 or 2.
To do this, map each number in your array to its corresponding remainder by modulo k. For this, create a new array remainders in which an index stands for a remainder, and a value stands for numbers having such remainder.
Go over the new array remainders and handle 3 cases.
4.1 If remainders[0] > 0, then we can still pick only one element from the original (if we pick more, then sum of their remainders 0, so they are divisible by k!!!).
4.2 if k is even and remainders[k/2] > 0, then we can also pick only one element (otherwise their sum is k!!!).
4.3 What about the other numbers? Well, for any remainder rem > 0 make sure to pick max(remainders[rem], remainders[k - rem]). You can't pick both since rem + k - rem = k, so numbers from such groups can be divisible by k.
Now, the code:
int nonDivisibleSubset(int k, int s_count, int* s) {
static int remainders[101];
for (int i = 0; i < s_count; i++) {
int rem = s[i] % k;
remainders[rem]++;
}
int maxSize = 0;
bool isKOdd = k & 1;
int halfK = k / 2;
for (int rem = 0; rem <= halfK; rem++) {
if (rem == 0) {
maxSize += remainders[rem] > 0;
continue;
}
if (!isKOdd && (rem == halfK)) {
maxSize++;
continue;
}
int otherRem = k - rem;
if (remainders[rem] > remainders[otherRem]) {
maxSize += remainders[rem];
} else {
maxSize += remainders[otherRem];
}
}
return maxSize;
}
When I try to write a small program in C language that is intended to generate a 4-digit integer for which every digit is distinct and nonzero, the returned value is always in pattern like 1abc: the first digit seems to always be 1, and sometimes the returned value will be more than 4-digit like 56127254. Could anyone help me look into this? Thank you very much in advance.
So basically the program includes two functions, int isvalid(int n) and int choose_N(void).
isValid return 1 if the integer consists of exactly 4 decimal digits, and all these digits are nonzero and distinct, and 0 otherwise.
And int choose_N(void) generates an integer that is 4-digit and all the digits are distinct and nonzero.
Here is my code:
#define N_DIGITS 4
....
....//the main function
int isvalid(int n){
int i, x; int check[N_DIGITS]={0};
for(i=1;i<=N_DIGITS;i++){ //check whether all digits are nonzero
if((check[i-1]=n%10)==0){
return 0;
}
n /= 10;
}
for(i=0;i<N_DIGITS-1;i++){ // check whether all digits are distinct
for(x=i+1;x<N_DIGITS;x++){
if(check[i]==check[x])
return 0;
}
}
return 1;
}
int choose_N(void){
int i; int number=0;
while(!isvalid(number)){
for(i=0;i<N_DIGITS;i++){
srand(time(0));
number += ((10^i)*(rand()%10));
}
}
return number;
}
For srand(time(0));, I have tried various alternatives like srand(time(0)+i); or put this statement out of while loop, but those attempts seemingly did not work and still the returned value of choose_Nstill showed the werid pattern that I described.
your choose_N method has several issues:
First, if the number isn't valid, you're not resetting it to 0, so it just grows and grows.
Second, srand(time(0)) is not necessary within the loop (and could yield the same result for several iterations), just do it at program start (srand() — why call it only once?)
Third and biggest mistake: 10 ^ i is 10 xor i, not 10**i. You can use an aux value and multiply by 10 in your loop. Since number of digits is low, no risk of overflow
minor remark: you want to pass in the loop at least once, so use a do/while construct instead, so you don't have to force the first while test.
I'm trying to fix your code:
int choose_N(void){
int i, number;
do
{
number = 0;
int p = 1;
for(i=0;i<N_DIGITS;i++)
{
number += p*(rand()%10);
p *= 10;
}
} while(!isvalid(number));
return number;
}
While #Jean-François-Fabre answer is the right one, it is not optimal algorithm. Optimal algorithm in such case would be using FIsher-Yates-Knuth shuffle and Durstenfeld's implementation.
Shuffling right array will produce numbers which are automatically valid, basically no need for isvalid(n) anymore.
Code
// Swap selected by index digit and last one. Return last one
int
swap_array(int digits[], int idx, int last) {
if (idx != last) { // do actual swap
int tmp = digits[last];
digits[last] = digits[idx];
digits[idx] = tmp;
}
return digits[last];
}
int
choose_N_Fisher_Yates_Knuth() {
int digits[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
int r = 0;
for (int k = 0; k != N_DIGITS; ++k) {
int idx = rand() % (9 - k);
int n = swap_array(digits, idx, (9 - k) - 1);
r = r * 10 + n;
}
return r;
}
int
main() {
srand(12345);
int r, v;
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
r = choose_N_Fisher_Yates_Knuth();
v = isvalid(r);
printf("%d %d\n", r, v);
return 0;
}
Output
7514 1
6932 1
3518 1
5917 1
with fear that I may overstep another question of mine (although this is a new problem alltogether) I still ask this question.
I have this code:
int blob_count(int y, int x, int gridCopy[][5], int sum){
//Local vars
int posX, posY;
//Find the position 1 behind and 1 above the starting point, and start the loop there
for(posX = -1;posX <=1; posX++){
for(posY = -1; posY <= 1; posY++){
if((y + posY) >= 0 && (x + posX) >= 0){
if((y + posY) <= 5 && (x + posX) <= 5){
if(gridCopy[posY+y][posX+x] == 1){
//Set the starting point to 0 (so it wont get calculated again)
gridCopy[posY+y][posX+x] = 0;
y = posY+y;
x = posX+x;
sum++;
blob_count(y, x, gridCopy, sum);
}
}
}
}
}
return sum;
}
The issue is that sum, which counts up 1, for each recursive run, returns the wrong value. By doing a print for each recursive run it gives the result:
sum = 1
sum = 2
sum = ...
sum = n
Which is great, however, by setting printing out the sum outside the for loop (right before return sum;) the opposite happens when it has peaked, so it does this:
sum = n
sum = ...
sum = 2
sum = 1
return sum; // = 1
Which is obviously wrong, as I want the total count, not the lowest. Have I got the return value the wrong place? I've tried putting it in right after the recursive call (inside the loop), to no avail.
Okay let's get rid of the extra bits and simplify your problem down to the essentials.
You have:
int blob_count(int sum)
{
sum++;
if (sum < 10)
blob_count(sum);
return sum;
}
If you add printf("sum==%d\n", sum) right before the return then it will be called first at the innermost recursion (where sum == 10), then it will return to the next level out where sum == 9, print that, return to sum == 8 and so on.
If you put it before the recursive call to blob_count(sum) then you'll print the values before you recurse down, so they start with sum==0, sum == 1 and so on.
If you want sumto be the deepest level your recursion got to, then you could either pass it back via the return value like this:
int blob_count(int sum)
{
sum++;
if (sum < 10)
sum = blob_count(sum);
return sum;
}
or you could pass it via a pointer so that the original variable gets modified:
void blob_count(int* sum)
{
*sum++;
if (*sum < 10)
blob_count(sum);
return;
}
The first one is probably the solution you are looking for.
What pmg said. For each recursive call, the current value of sum is copied and the copy is passed to the recursive call. If you want to modify objects in functions, you must pass a pointer to these objects instead of the object itself.