Recurrence relation for the algorithm - c

I have already given the following algorithm which I have to find the recurrence relation.
int Recursive(int n)
{
if(n<=1)
return n;
sum=0;
for(int j=0;j<n;j++)
sum++;
return Recursive(n/2) + Recursive(n/2) + sum;
}
I have obtained recurrence relation for the above algorithm as
T(n) = 2 T(n/2) + constant
But I am not sure about the constant part of this recurrence relation since we have sum in the algorithm. Just to clarify, sum is a global variable - the lack of declaration is not a typo.
Can anyone help me out to get the correct recurrence relation? Thanks.

Assumptions made in this answer:
sum is declared globally – since the apparently missing declaration is, as you stated, not a typo.
The question asks for the return value, not the time complexity.
The expressions in the return statement are evaluated in their order of appearance; this is not guaranteed by the C standard, so the answer is technically undefined.
Note that, since each call does either:
Returns its argument (if n <= 1)
Resets the value of sum to 0
... the function is guaranteed to be "closed", in the sense that its return value will only depend on its argument. It follows that:
The two separate calls to Recursive(n / 2) can be combined into just one call, without impacting the return value: return 2 * Recursive(n / 2) + sum;.
From this point on-wards is it assumed that this modification has been applied to the original code; this helps in clarifying the flow of the program, since there will now only be one path of execution (instead of branches created by two calls).
Now for the key part. The call to Recursive(n / 2) overwrites the value of sum before the function returns, undoing the work done by the preceding for-loop. This overwriting behavior continues down the recursion hierarchy, until the final call when the stopping condition n <= 1 is hit (it just returns n instead). It follows that:
There is only one value of sum which contributes to the final return value, given by its value after the penultimate call to Recursive.
Due to truncation by integer division, when the penultimate call is performed n is always 2 or 3 (both of which satisfy n / 2 = 1); these are thus also the possible final values of sum.
What values of n give sum = 2 and sum = 3 respectively? It is illustrative to consider the binary representation of n.
Integer division by 2 is equivalent to shifting the bit-pattern "right" by 1 (or "left" depending on endian-ness...), and discarding the least-significant bit. It follows that the final value of sum depends on only the 2 most significant bits of n:
initial bit-pattern >> penultimate call
-----------------------------------------
...000 10 xxx... ...0000 10 = 2
...000 11 xxx... ...0000 11 = 3
xxx: discarded bits
The bit-pattern of n has floor(log2(n)) + 1 significant bits; the final value of sum can therefore be compactly expressed as:
S(n) = 2 + second_most_significant_bit(n)
How many times is sum added to the return value? The number of recursive calls to Recursive (i.e. the total number of calls minus one, including the initial call, but excluding the final). This is given by floor(log2(n)):
Note that the return value of the final call will always be 1 if initially n >= 1. Therefore the final return value of Recursive is given by:
Test C code for confirmation:
// override the library definition of log2 to use integers only
int log2(int n) {
int b = 0;
while ((n >>= 1) != 0)
b++;
return b;
}
// get i-th bit from bit pattern of n
int get_bit(int n, int i) {
return (n >> (i - 1)) & 1;
}
// calculating return value of Recursive using equation above
int Value(int n) {
int l2n = log2(n); // floor(log2(n))
int p2l = 1 << l2n; // 2^(floor(log2(n)))
return p2l + (p2l - 1) * (2 + get_bit(n, l2n));
}
Results:
n | Recursive Value
-------------------------------
2 | 4 4
3 | 5 5
4 - 5 | 10 10
6 - 7 | 13 13
8 - 11 | 22 22
12 - 15 | 29 29
16 - 23 | 46 46
24 - 31 | 61 61
32 - 47 | 94 94
48 - 63 | 125 125
64 - 95 | 190 190

I am not sure about the constant part of this recurrence relation
There is no constant part, since sum equals n after the loop. This gives:
T(n) = 2T(n/2)+n
So if the sum is global variable, T(n) = 2T(n/2)+C(Constant) and if sum is local variable T(n) = 2T(n/2)+n . Am I correct?
No, as mch wrote:
It seems that sum is a global variable… In this case it would be unspecified if sum or one of the Recursive(n/2) will be evaluated first.
This means it would be unspecified whether T(n) = 2T(n/2)+n or T(n) = 2T(n/2)+n/2; in neither case there's a constant part.

Related

C Programming what happens exactly with this recursive function

i have this function that when i start it prints only even numbers of the entered parameter can anyone explain to me what exactly happens in this function and how it ends up getting the even numbers
#include <stdio.h>
int what(int x){
if (x == 0)
return 0;
if (x % 2 == 0)
return what(x / 10) * 10 + x % 10;
return what(x / 10);
}
int main(){
printf("%d\n",what(145825));
return 0;
}
output
482
Here's what happens:
The what() function starts with the rightmost digit (= the whole number modulo 10) and then recurses into the rest of the digits by throwing away the rightmost digit (integer division by 10 throws away the right decimal digit).
If the right digit is even it is appended to the result of the recursion by multiplying it by 10 (making space for the extra digit on the right) and adding this digit (= the whole number modulo 10).
If the right digit is odd nothing is added to the result of the recursion.
Recursion stops when there are no more digits.
A good way to figure out to make recursion is to make a table that keeps track of what happens during each step, but of course a debugger is always the best way to really check what happens.
The following table is what happens each time what() is called:
x recursive x result even? returns
------ ----------- ------ ------- -------
145825 14582 482 - 482
______/ \_____________
/ \
14582 1458 48 48*10+2= 482
1458 145 4 4*10+8= 48
145 14 4 - 4
14 1 0 0*10+4= 4
1 0 0 - 0
0 - - - 0

bitwise operator XOR [duplicate]

This question already has answers here:
How does XOR work in C to find a number occurring odd number of times?
(4 answers)
Closed 6 years ago.
Trying to understand the XOR importance, I found this code:
Given a set of numbers where all elements occur even number of times except one number, find the odd occurring number
But I can't visualize it.
How does the XOR bitwise operator roll out the odd element?
// Function to return the only odd occurring element
int findOdd(int arr[], int n) {
int res = 0, i;
for (i = 0; i < n; i++)
res ^= arr[i];
return res;
}
int main(void) {
int arr[] = { 12, 12, 14, 90, 14, 14, 14 };
int n = sizeof(arr) / sizeof(arr[0]);
printf("The odd occurring element is %d\n", findOdd(arr, n));
return 0;
}
Output: The odd occurring element is 90
The way I read it you are really asking two questions:
What is the importance of XOR?
How does XOR help find the odd occurrence of a number in a series?
In order to understand question (2), one must understand question (1). Understanding question (1) requires an adequate introduction to the XOR logic and the properties it has.
What is the importance of XOR?
Definition: The output of an XOR operation is TRUE if and only if the number of TRUE inputs are odd. Commonly referred to as "one or the other, but not both"
This is captured by the following truth table:
XOR Truth Table
Using the truth table it is trivial to derive the following properties:
A ^ 0 = A (The output follows the variable input)
A ^ 1 = A' (The output is the negation of the variable input)
A ^ A = 0 (The output is always zero since both inputs are equal)
(A ^ B) ^ C = A ^ (B ^ C) (Associative Property)
A ^ B = B ^ A (Communative Property)
Now on to the importance of XOR, i.e., how these properties allow folks to make useful things. The first computing layer to note is the hardware layer. XOR gates are physical devices that have utility in many fundamental logic circuits, that fundamental utility being "odd occurrence detection". Some notable applications:
Half-Adders: The truth table for a half-adders SUM output is identical to the XOR gate. (Throw an AND gate in for the carry bit). Same thing for the Full-Adder, using XOR gates for the fundamental summation with some additional supporting gates.
Inverters: Using one input as a control and the other as the "input", the xor gate can be used to invert the input signal. The control bit can be used to pass the input through as well, acting as a buffer. In software, you use these circuits to toggle bits/bytes from one state to the other. Val = Val ^ 1 (Recall the second property above).
Comparators: The output of an XOR gate is 1 when the inputs are different, 0 when they are the same. This is the driving logic for the half-adder.
In addition to these circuits we can, at a hardware level, use XOR to check byte parity for Error Detection and Correction (EDAC) operations, swap register values (without a temp variable!), and recover corrupted/lost data from hard drives in a RAID system.
However, software junkies don't care about these circuits, they want to live in the land of abstractions that provide an easy way to use this hardware in a human intuitive way. Let there be code.
How does XOR help find the odd occurrence of a number in a series?
Even though the first comment to your question indicates the poster didn't understand your question, they inadvertently answered the question correctly, but I will explain further.
Let's break down what your findOdd() function is actually doing. The for loop is literally performing the following calculation:
Result = 0 ^ 12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14
Recall that XOR is communative, so after a little re-ordering the calculation becomes:
Result = 0 ^ 12 ^ 12 ^ 14 ^ 14 ^ 14 ^ 14 ^ 90
Using the property A ^ A = 0 and associativity, the XOR of 12 and 12 drops to 0 as does the XOR of the 14's, leaving:
Result = 0 ^ 0 ^ 0 ^ 0 ^ 90 = 0 ^ 90 = 90
In effect, the XOR forces even occurrences to become zero and A ^ 0 = A. Hope this verbose description of XOR was helpful in visualizing what is happening under the hood.
Binary XOR is the exclusive or operation, performed one bit at a time. It is equivalent to subtraction, modulo 2.
Here is the truth table for XOR:
a b a^b
1 0 1
1 1 0
0 0 0
0 1 1
As you can see, XOR sets a bit to 1 (true) when EITHER of the input bits is 1, but not both.
Now, consider this: what is 1 xor 1? From the truth table, you know it's zero.
And what is 1 xor 1 xor 1? Well, you know 1^1==0, so that leaves 0^1, which is 1.
So you have that xor'ing a 1 bit an even number of times will produce a zero, and an odd number of times will produce a 1.
Thus, if we take a ^ a ^ a, for some value of a, we get a result where all the 1 bits in the binary representation of a are set. (Which is to say, we get back 'a'.)
Whereas if we take a ^ a ^ a ^ a, for some value of a, we get a result where all the 1 bits in the binary representation of a are 0. (Which is to say, we get back 0.)
The one exception to this, of course, is 0. The binary representation for 0 has no set bits in it, so this approach will not indicate if the number of 0's was even or odd.
But I can't visualize it
Then you should step through the code one line at a time and keep an eye on res at each iteration through the loop.
Or just do it on paper -- write down the binary form of 12, i.e. 00001100, and then XOR that value with the next value, also 00001100, which gets you back to 00000000. Then XOR the next value with that, and so on. You might want to start with a short list of pairs of numbers, like {12, 12, 15, 15} and see what happens. Then try removing the last one, so you have {12, 12, 15} and see what you get. Then try reordering the list: {12, 15, 12}. Count the number of times that each bit gets flipped.
XOR means exclusive or, for each bit in the operands, the resulting bit is 1 if either corresponding bit of the operand is 1 but not both:
0 ^ 0 = 0, 1 ^ 0 = 1, 1 ^ 0 = 0 and 1 ^ 1 = 0.
Identical numbers cancel each other as x ^ x == 0 for all values. The final outcome of xoring all elements of the array is the number occurring an odd number of times, assuming there is only one.
This method works if all duplicate numbers but one occur an even number of times and if there is a single entry occurring an odd number of times.
XOR is commutative: a ^ b equals b ^ a.
XOR is associative: a ^ (b ^ c) equals (a ^ b) ^ c.
Together these two mean that you can arbitrarily reorder operands in a chain of XORs.
Furthermore:
0 is a neutral element: a ^ 0 equals a.
Every number is its own inverse: a ^ a equals 0.
In your code we're doing 12 ^ 12 ^ 14 ^ 90 ^ 14 ^ 14 ^ 14.
We can reorder this to (12 ^ 12) ^ (14 ^ 14) ^ (14 ^ 14) ^ 90, pairing up every element that occurs an even number of times with itself.
This simplifies to 0 ^ 0 ^ 0 ^ 90 (because all pairs of equal elements cancel each other out, giving 0), which reduces to just 90 (because XORing with 0 does nothing).
This is all about XOR operator.
^ is bit-wise XOR.
For example,
12^5 == 1100^0101 == (1^0)(1^1)(0^1)(0^1) == 1011
From the mathematical definition of XOR, the output is 1 iif the number of 1(s) in inputs is odd.
This case:
When a number occurs even number of times, the binary representation will also get two 1s or two 0s in each position, making the result going to 0.
Eg:
2^2^3 == (1^1^1)(0^0^1) == 11 == 3
i.e. 10 (2)
10 (2)
11 (3)
--------
11 (3)
========
5^7^5 == (1^1^1)(0^1^0)(1^1^1) == 111
101 (5)
111 (7)
101 (5)
---------
111 (7)
=========
Note that even occurring numbers have no affect here.
Given the following axioms:
x ^ x == 0
y ^ y ^ y == y
z ^ 0 == z
Then for example:
x ^ x ^ y ^ y ^ y == y
\___/ \_______/
0 ^ y == y
Also:
x ^ y == y ^ x
So the order of the operands does not matter.
The point is an odd number of occurrences of a value results in the value, while even results in zero, and a value xor'ed with zero is the value.
Consequently as the comment at the start of the code suggests, it works only when there is a single value with an odd number of occurrences and all other values occur an even number of times. Otherwise the result is simply the xor of all the odd occurring values, e.g.:
x ^ x ^ x ^ y == x ^ y
which is neither x nor y.

How to express this mathematical relation in a c program

How to create a c code that receive int parameter n and return the value of this mathematical equation
f(n) = 3 * f(n - 1) + 4, where f(0) = 1
each time the program receive n , the program should start from the 0 to n which means in code (for loop) .
the problem here that i can't translate this into code , I'm stuck at the f(n-1) part , how can i make this work in c ?
Note. this code should be build only in basic C (no more the loops , no functions , in the void main etc) .
It's called recursion, and you have a base case where f(0) == 1, so just check if (n == 0) and return 1 or recurse
int f(int n)
{
if (n == 0)
return 1;
return 3 * f(n - 1) + 4;
}
An iterative solution is quite simple too, for example if f(5)
#include <stdio.h>
int
main(void)
{
int f;
int n;
f = 1;
for (n = 1 ; n <= 5 ; ++n)
f = 3 * f + 4;
printf("%d\n", f);
return 0;
}
A LRE (linear recurrence equation) can be converted into a matrix multiply. In this case:
F(0) = | 1 | (the current LRE value)
| 1 | (this is just copied, used for the + 4)
M = | 3 4 | (calculates LRE to new 1st number)
| 0 1 | (copies previous 2nd number to new 2nd number (the 1))
F(n) = M F(n-1) = matrixpower(M, n) F(0)
You can raise a matrix to the power n by using repeated squaring, sometimes called binary exponentiation. Example code for integer:
r = 1; /* result */
s = m; /* s = squares of integer m */
while(n){ /* while exponent != 0 */
if(n&1) /* if bit of exponent set */
r *= s; /* multiply by s */
s *= s; /* s = s squared */
n >>= 1; /* test next exponent bit */
}
For an unsigned 64 bit integer, the max value for n is 40, so the maximum number of loops would be 6, since 2^6 > 40.
If this expression was calculating f(n) = 3 f(n-1) + 4 modulo some prime number (like 1,000,000,007) for very large n, then the matrix method would be useful, but in this case, with a max value of n = 40, recursion or iteration is good enough and simpler.
Best will be to use recursion . Learn it online .
Its is very powerful method for solving problems. Classical one is to calculate factorials. Its is used widely in many algorithms like tree/graph traversal etc.
Recursion in computer science is a method where the solution to a problem depends on solutions to smaller instances of the same problem.
Here you break you problem of size n into 3 instance of sub problem of size n-1 + a problem of constant size at each such step.
Recursion will stop at base case i.e. the trivial case here for n=0 the function or the smallest sub problem has value 1.

How do I manipulate the digits of a number?

In some kinds of problems I often face this situation where I have a variable where I need to rearrange the digits, e.g., int e = 2385;. Let's suppose I don't know which number is stored there, but still I need to shift 2nd and 4th position. When I know variable's value I can simply do e = 2583, but when I don't know I simply can't solve the problem.
Another situation is when I have two values and want to use them to form another number i.e int a = 2, b = 1;, and I need to order them so that I will get a 21 or a 212. I mean, that's easy to do when I'm outputting data, I can simply do:
printf("%d%d\n",a,b);
printf("%d%d%d",a,b,a);
Problem is when I have to store this number in another variable. I don't know how to do that.
This can be broken into two tasks: (1) breaking up a number into pieces, and (2) combining pieces into a whole number.
To break up a number into pieces, use the division and modulus operators.
int num = 2385;
int a = num / 1000; // 2
int b = num / 100 % 10; // 3
int c = num / 10 % 10; // 8
int d = num / 1 % 10; // 5
The trick is to use division to remove the digits to the right, then modulus to keep only the rightmost digit. For example, to calculate the hundreds' place (b) we compute 2385 / 100, which is 23. 23 % 10 is the remainder when you divide 23 by 10. The remainder is 3.
To combine the pieces back into a number, do the opposite with multiplication and addition.
num = a * 1000 // 2000
+ d * 100 // + 500
+ c * 10 // + 80
+ b * 1; // + 3
// ----
// 2583
Notice how I switched d and b to swap those digits.

++group((int)(value[i])/10); what does it do..? in C

This program is for calculating students marks frequency
float value[50];
int group[11] = {0};
for (i = 0; i < 50; i++) {
scanf("%f",&value[i]); /* reading of values */
++group[(int)(value[i])/10)]; /* what does this line do.? */
}
This line:
++group[(int)(value[i]) / 10)];
Is the same as:
int flooredValue = (int)value[i]; //e.g. 3.5 becomes 3; 12.6 becomes 12
int groupIndex = flooredValue / 10; //division discarding the remainder
group[groupIndex] += 1;
What does it mean, though? Well here's how it ends up converting the values:
value[i] | groupIndex
----------+------------
3.5 | 0
12.6 | 1
18.6 | 1
23.1 | 2
57 | 5
94.6 | 9
100 | 10
So it ends up counting how many marks fall into each bucket of 10. Scores from 0 to 9.9999 fall in the "0" bucket, from 10 to 19.99999 in the "1" bucket, etc. Note the following, though:
value[i] | groupIndex
-----------+------------
-3.5 | -3
155.6 | 15
As it is now, your input could certainly be less than zero or over 100. If that happens, you're going to write into memory outside of the bounds of group. This will lead to very unpleasant behavior. Check either that the input value is in bounds or that the group index is in bounds before indexing into the group array.
++group[(int)(value[i])/10)];
lets divide this
1. (int)(value[i])/10)
for example value[i] is 51 it will result 5 as you are using casting to int.
2. ++group[5]; // is same as group[5] += 1;
pre incrementing value of group[5]
In sub-expression
(int)(value[i])/10)
value[i] is of type float, dividing it by 10 will give double value (after default promotion). But array subscripts should be of integer type, (int) is used to cast the return value of sub-expression to integer .
In expression
++group[(int)(value[i]) / 10)];
prefix ++ is used to pre-increment the array element group[(int)(value[i])/10)].

Resources