Calculate the average of an array with a recursive function - c

How would you write a recursive function that calculates the average of the elements of an array?
Here's what I have so far:
int media(int numeros[], int i, int n) {
if (i == n-1) return numeros[i]/n;
return numeros[i]/n + media(numeros, i + 1, n);
}
But it doesn't work, and I think it's because of the line: if (i == n-1) return numeros[i]/n;

How about this:
double media(int numeros[], int i, int n) {
if (i == n - 1) {
return numeros[i];
}
if (i == 0)
return ((numeros[i] + media(numeros, i + 1, n)) / n);
else
return (numeros[i] + media(numeros, i + 1, n));
}
What you're doing is dividing by the number of elements each call - doing that will give you the incorrect average. The code above does what you were doing, but as its about to return the result (when i==0) it'll calculate the actual average based on the total of all the elements

The problem is that if you divide each element, because of rounding (to integer), you'll quite probably get an incorrect answer (integer divide by integer returns integer).
For {1,2,3,4}, we'll divide each element by 4 - 1/4 + 2/4 + 3/4 + 4/4, but each division returns an integer, so all of them are 0 and the result is 0.
So, either make it double: (but it's still better to also divide at the end, because of rounding)
double media(int numeros[], int i, int n){
if (i == n-1) return 1.0*numeros[i-1]/n;
return 1.0*numeros[i]/n + media(numeros, i + 1, n);
}
Or divide at the end: (either the way Sean Landsman suggested, or like below)
int media(int numeros[], int i, int n){
if (i == -1) return media(numeros, 0, n)/n;
if (i == n-1) return numeros[i-1];
return numeros[i] + media(numeros, i + 1, n);
}
Caller:
int media(array, -1, n);

Related

What is the time complexity of exponentiation by squaring?

Here is a code to exponentiate a number to a given power:
#include <stdio.h>
int foo(int m, int k) {
if (k == 0) {
return 1;
} else if (k % 2 != 0) {
return m * foo(m, k - 1);
} else {
int p = foo(m, k / 2);
return p * p;
}
}
int main() {
int m, k;
while (scanf("%d %d", &m, &k) == 2) {
printf("%d\n", foo(m, k));
}
return 0;
}
How do I calculate the time complexity of the function foo?
I have been able to deduce that if k is a power of 2, the time complexity is O(log k).
But I am finding it difficult to calculate for other values of k. Any help would be much appreciated.
How do I calculate the time complexity of the function foo()?
I have been able to deduce that if k is a power of 2, the time complexity is O(logk).
First, I assume that the time needed for each function call is constant (this would for example not be the case if the time needed for a multiplication depends on the numbers being multiplied - which is the case on some computers).
We also assume that k>=1 (otherwise, the function will run endlessly unless there is an overflow).
Let's think the value k as a binary number:
If the rightmost bit is 0 (k%2!=0 is false), the number is shifted right by one bit (foo(m,k/2)) and the function is called recursively.
If the rightmost bit is 1 (k%2!=0 is true), the bit is changed to a 0 (foo(m,k-1)) and the function is called recursively. (We don't look at the case k=1, yet.)
This means that the function is called once for each bit and it is called once for each 1 bit. Or, in other words: It is called once for each 0 bit in the number and twice for each 1 bit.
If N is the number of function calls, n1 is the number of 1 bits and n0 is the number of 0 bits, we get the following formula:
N = n0 + 2*n1 + C
The constant C (C=(-1), if I didn't make a mistake) represents the case k=1 that we ignored up to now.
This means:
N = (n0 + n1) + n1 + C
And - because n0 + n1 = floor(log2(k)) + 1:
floor(log2(k)) + C <= N <= 2*floor(log2(k)) + C
As you can see, the time complexity is always O(log(k))
O(log(k))
Some modification added to output a statistics for spread sheet plot.
#include <stdio.h>
#include <math.h>
#ifndef TEST_NUM
#define TEST_NUM (100)
#endif
static size_t iter_count;
int foo(int m, int k) {
iter_count++;
if (k == 0) {
return 1;
} else if(k == 1) {
return m;
} else if (k % 2 != 0) {
return m * foo(m, k - 1);
} else {
int p = foo(m, k / 2);
return p * p;
}
}
int main() {
for (int i = 1; i < TEST_NUM; ++i) {
iter_count = 0;
int dummy_result = foo(1, i);
printf("%d, %zu, %f\n", i, iter_count, log2(i));
}
return 0;
}
Build it.
gcc t1.c -DTEST_NUM=10000
./a > output.csv
Now open the output file with a spread sheet program and plot the last two output columns.
For k positive, the function foo calls itself recursively p times if k is the p-th power of 2. If k is not a power of 2, the number of recursive calls is strictly inferior to 2 * p where p is the exponent of the largest power of 2 inferior to k.
Here is a demonstration:
let's expand the recursive call in the case k % 2 != 0:
int foo(int m, int k) {
if (k == 1) {
return m;
} else
if (k % 2 != 0) { /* 2 recursive calls */
// return m * foo(m, k - 1);
int p = foo(m, k / 2);
return m * p * p;
} else { /* 1 recursive call */
int p = foo(m, k / 2);
return p * p;
}
}
The total number of calls is floor(log2(k)) + bitcount(k), and bitcount(k) is by construction <= ceil(log2(k)).
There are no loops in the code and the time of each individual call is bounded by a constant, hence the overall time complexity of O(log k).
The number of times the function is called (recursively or not) per power call is proportional to the minimum number of bits in the exponent required to represent it in binary form.
Each time you enter in the function, it solves by reducing the number by one if the exponent is odd, OR reducing it to half if the exponent is even. This means that we will do n squares per significant bit in the number, and m more multiplications by the base for all the bits that are 1 in the exponent (which are, at most, n, so m < n) for a 32bit significant exponent (this is an exponent between 2^31 and 2^32 the routine will do between 32 and 64 products to get the result, and will reenter to itself a maximum of 64 times)
as in both cases the routine is tail-recursive, the code you post can be substituted with an iterative code in which a while loop is used to solve the problem.
int foo(int m, int k)
{
int prod = 1; /* last recursion foo(m, 0); */
int sq = m; /* squares */
while (k) {
if (k & 1) {
prod *= sq; /* foo(m, k); k odd */
}
k >>= 1;
sq *= sq;
}
return prod; /* return final product */
}
That's huge savings!!! (between 32 multiplications and 64 multiplications, to elevate something to 1,000,000,000 power)

Find the minimum number of steps to decrease N to zero

I'm facing some difficulties in the last few days while trying to finish the following task, I hope you guys can assist :
I'm given a single number N, and I'm allowed to perform any of the two operations on N in each move :
One - If we take 2 integers where N = x * y , then we can change the value of N to the maximum between x and y.
Two - Decrease the value of N by 1.
I want to find the minimum number of steps to reduce N to zero.
This is what I have so far, I'm not sure what is the best way to implement the function to find the divisor (someFindDevisorFunction), and if this 'f' function would actually produce the required output.
int f(int n)
{
int div,firstWay,secondWay;
if(n == 0)
return 0;
div = SomefindDivisorFunction(n);
firstWay = 1 + f(n-1);
if(div != 1)
{
secondWay = 1 + f(div);
if (firstWay < secondWay)
return firstWay;
return secondWay;
}
return firstWay;
}
For example, if I enter the number 150 , the output would be :
75 - 25 - 5 - 4 - 2 - 1 - 0
I see this a recursive or iterative problem.
OP's approach hints at recursive.
A recursive solution follows:
At each step, code counts the steps of the various alternatives:
steps(n) = min(
steps(factor1_of_n) + 1,
steps(factor2_of_n) + 1,
steps(factor3_of_n) + 1,
...
steps(n-1) + 1)
The coded solution below is inefficient, but it does explore all possibilities and gets to the answer.
int solve_helper(int n, bool print) {
int best_quot = 0;
int best_quot_score = INT_MAX;
int quot;
for (int p = 2; p <= (quot = n / p); p++) {
int rem = n % p;
if (rem == 0 && quot > 1) {
int score = solve_helper(quot, false) + 1;
if (score < best_quot_score) {
best_quot_score = score;
best_quot = quot;
}
}
}
int dec_score = n > 0 ? solve_helper(n - 1, false) + 1 : 0;
if (best_quot_score < dec_score) {
if (print) {
printf("/ %d ", best_quot);
solve_helper(best_quot, true);
}
return best_quot_score;
}
if (print && n > 0) {
printf("- %d ", n - 1);
solve_helper(n - 1, true);
}
return dec_score;
}
int main() {
int n = 75;
printf("%d ", n);
solve(n, true);
printf("\n");
}
Output
75 / 25 / 5 - 4 / 2 - 1 - 0
Iterative
TBD
If you start looking for a divisor with 2, and work your way up, then the last pair of divisors you find will include the largest divisor. Alternatively you can start searching with divisor = N/2 and work down, when the first divisor found will have be largest divisor of N.
int minmoves(int n){
if(n<=3){
return n;
}
int[] dp=new int[n+1];
Arrays.fill(dp,-1);
dp[0]=0;
dp[1]=1;
dp[2]=2;
dp[3]=3;
int sqr;
for(int i=4;i<=n;i++){
sqr=(int)Math.sqrt(i);
int best=Integer.MAX_VALUE;
while(sqr >1){
if(i%sqr==0){
int fact=i/sqr;
best=Math.min(best,1+dp[fact]);
}
sqr--;
}
best=Math.min(best,1+dp[i-1]);
dp[i]=best;
}
return dp[n];
}

Sine value using recursive function in C

I am getting negative and positive result : when I enter(n value odd) odd term produces even or and even term produces odd value. I have already made function for factorial it works fine.
#include <stdio.h>
#include <math.h>
#define PI 3.14159f
int factorial(int n);
float sine(float , int);
int i;
void main(){
float degree;
float radian;
float result;
int n;
printf("Enter the angle in degree: ");
scanf("%f",&degree);
printf("Enter the iteration: ");
scanf("%d",&n);
radian = degree * PI / 180;
result = sine(radian,n);
printf("%d",factorial(n));
printf("\n");
printf("sin%.2f = %.3f",degree,result);
}
int factorial(int n)
{
if(n==0)
return 1;
else if (n==1)
return 1;
else
return (n*factorial(n-1));
}
float sine(float an, int n)
{
if (an==0)
return 0;
else if(n>=0)
if(n%2==1)
return (sine(an,n-2) - pow(an,n)/factorial(n)) * pow(-1,n);
else
return (sine(an,2*n-1) - pow(an,2*n+1)/factorial(2*n+1)) *-1 ;
}
float sine(float an, int n)
{
if (an == 0)
return 0;
The above condition returns 0 for sin(0) so it is of no use in rest of the recursion and it works fine.
else if(n >= 0)
if(n%2 == 1)
return (sine(an,n-2) - pow(an,n)/factorial(n)) * pow(-1,n);
else
return (sine(an,2*n-1) - pow(an,2*n+1)/factorial(2*n+1)) *-1 ;
Lets see where this part of your function goes, by substituting the value of n:
Suppose we are start with degree = 30 and number of iterations = 3
Then:
n = 3;
n is odd so function returns:
((sine(an, 3-2) - (float)pow(an, 3) / factorial(3)) * -1);
n = 1;
n is again odd so function returns:
((sine(an, 1-2) - (float)pow(an, 1) / factorial(1)) * -1);
n = -1;
This time n < 0 so if-else conditions are skipped and some garbage value is returned because you did not tell your program what to return at n = 0
So you need your sine-function to return a default value when n = 0
pow(-1,n) will always return -1 for odd values of n, and 1 for even values of n. So the sign of output of sine() function is not changing alternately like in the series.
Answering to the comment: Why the sign seems to change for odd or even,
In your code values of n are skipping the even numbers, instead of decreasing n by 1 per call, you are passing only odd numbers.
return (sine(an,n-2) - pow(an,n)/factorial(n)) * pow(-1,n);
so what you get in the end is a sum of negatives; And when you start with a even value of n like 2, then sine() is called with odd value of n the second time which is (2*n-1) which again returns a sum of negatives.
Heres what you can do:
float sine(float an, int n)
{
if (an == 0 || n == 0)
return 0; //to end the recursion when number of iterations are finished
else
return -1*pow(-1,n)*pow(an,2*n-1)/factorial(2*n-1) + sine(an, n - 1);
}
// `-1*pow(-1,n)` returns a negative term for even value of n, and postive term for odd value of n as required. You dont need separate if-else for that

subset sum with negative values in c or c++

I have this code for finding the subset sum of positive values and everywhere I searched I only see positive integers or a program written in java in advanced level. I want to know how to implement that my C program would work with negative numbers. Actually, I want it to find sum that is 0. I had an idea
Take the minimum value in the set, call it k.
Add each element in the set by the absolute value of k.
Add sum by the absolute value of k.
Perform the algorithm.
But I found that this wont work. Take the set (-5, 10) and see if any subset adds up to 5. We would convert (-5, 10) -> (0, 15) and 5->10. -5+10=5, but 0+15 != 10
A lot of ideas I searched on the internet but can't find the answer.
#include <stdio.h>
typedef int bool;
#define true 1
#define false 0
bool isSubsetSum(int set[], int n, int sum) {
// Base Cases
if (sum == 0)
return true;
if (n == 0 && sum != 0)
return false;
if (set[n - 1] > sum)
return isSubsetSum(set, n - 1, sum);
return isSubsetSum(set, n - 1, sum) ||
isSubsetSum(set, n - 1, sum - set[n - 1]);
}
int main() {
int set[] = { -3, 34, -2, 12, 5, 8 };
int sum = 0;
int i;
int n = sizeof(set) / sizeof(set[0]);
if (isSubsetSum(set, n, sum) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
I dont really understand your strategy. You should not use the absolute value. The sum of a+b has little to do with the sum of |a|+|b| (well there are some relations, but if you use them somewhere then I missed it ;).
If you have an algorithm that can find you a subset among positive integers that adds up to x, then you can use it also for negative numbers. It wont be as efficient, but with a small trick it can work....
First you add an offset to all numbers to make them all positive. Now you look for subsets that add up to x+y*offset, where y is the size of the subset. Eg. you have
A = -1, -3, -2, 6 12, 48
and you are looking for a subset that adds up to 0, then you first add 3 to all numbers,
b = 2, 0, 1, 9, 15, 51
and then try to find a subset of size 1 that adds up to 3, a subset of size 2 that adds up to 6, ...., a subset of size 4 that adds up to 12, that would be
12 = 2+0+1+9 ie 0 = -1 + -3 + -2 + 6
Doing it that way isnt very efficient, because you have to apply the algorithm N-times (N= size of input). However, if your algorithm for positives lets you fix the size of the subset, this may compensate this loss in efficiency.
I guess you can try a brute force attempt by removing the test for overflow:
#include <stdio.h>
int isSubsetSum(int set[], int n, int sum, int empty_ok) {
// Base Cases
if (sum == 0 && empty_ok)
return 1;
if (n == 0)
return 0;
return isSubsetSum(set, n - 1, sum, empty_ok) ||
isSubsetSum(set, n - 1, sum - set[n - 1], 1);
}
int main(void) {
int set[] = { 3, 34, 2, 12, 5, 8 };
int n = sizeof(set) / sizeof(set[0]);
int sum = 6;
if (isSubsetSum(set, n, sum, 0) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
Unfortunately, the time complexity of this solution is O(2n).
Here is a non recursive solution for sets up to 64 elements:
int isSubsetSum(int set[], int n, int sum) {
unsigned long long last;
if (n == 0)
return sum == 0;
last = ((1ULL << (n - 1)) << 1) - 1;
// only find non empty subsets for a 0 sum
for (unsigned long long bits = 1;; bits++) {
int s = 0;
for (int i = 0; i < n; i++) {
s += set[i] * ((bits >> i) & 1);
}
if (s == sum)
return 1;
if (bits == last)
return 0;
}
}
Explanation: type unsigned long long is guaranteed to have at least 64 value bits. bits varies from 1 to last inclusive and takes all possible bit patterns of n bits except all off. For each value of bits, I sum the elements for which the corresponding bit is set, hence all possible non empty subsets are tested.
Code has TBD bug
Yet OP requested it to remain. I fix it later or take down tomorrow.
OP's code has trouble because it is searching for the wrong sum.
By finding the minimum value and offsetting each element of set[], the problem becomes one of only positive numbers - which apparently OP has solved prior.
The trick is that the target sum needs to be offset by n*offset
#include <stdio.h>
#include <stdbool.h>
//typedef int bool;
//#define true 1
//#define false 0
bool isSubsetSum(int set[], int n, int sum, int offset) {
// Base Cases
if ((sum + n*offset) == 0)
return true;
if (n == 0 && (sum + n*offset) != 0)
return false;
if (set[n - 1] > sum + n*offset)
return isSubsetSum(set, n - 1, sum, offset);
return isSubsetSum(set, n - 1, sum, offset) ||
isSubsetSum(set, n - 1, sum - set[n - 1], offset);
}
int main() {
int set[] = { -3, 34, -2, 12, 5, 8 };
int sum = 0;
int i;
int n = sizeof(set) / sizeof(set[0]);
int min = -3; // TBD code to find minimum
for (i = 0; i<6; i++) set[i] -= min;
if (isSubsetSum(set, n, sum, -min) == true)
printf("Found a subset");
else
printf("No subset");
return 0;
}
Found a subset

C Program: Adding a series using recursion

I am new to recursion so I am trying to write a simple program that adds to the nth number of the series 1/n. So if the user enters n = 4, the program will add 1 + 1/2 + 1/3 + 1/4. My program keeps outputting that the sum of the series is 0. Can someone please explain what I am doing wrong? I'd appreciate the help. Here is my code:
#include <stdio.h>
double sum(double n);
int main() {
double n;
double total;
printf("Enter a positive integer greater than 0: ");
scanf("%lf", &n);
total = sum(n);
printf("Sum: %lf", total);
return 0;
}
double sum(double n) {
if (n == 1)
return 1;
else
return ((1 / n) + sum(n - 1));
}
The problem is in the definition of this function:
double sum(int n) {
if (n == 1)
return 1;
else
return ((1 / n) + sum(n - 1));
}
n is int so 1/n will be always evaluated as int since both 1 and n are integers. Thus 1/n is always 0 for each n>1.
The solution would be to define n as double :
double sum(double n) {
if (n <= 1.0)
return 1.0;
else
return ((1.0 / n) + sum(n - 1.0));
}
Check your base case. sum(1) should return 1.
Also, an int divided by an int returns an int. Use a floating point number in your division.
It should be
double sum(double n) {
if (n == 1)
return 1.0;
else
return ((1.0 / n) + sum(n - 1));
}
1/n will always return 0 since 'n' acts as an integer value and not a float value even though the datatype is double as the value assigned to it is of type integer.

Resources