Implementation of a double factorial tail-recursive function in C - c

I got stuck trying to implement the following formula in my C code:
N!! = N!/(N-1)!!
The code is supposed to be a tail-recursive function, and although it does work and the computation is correct, I'm pretty sure this is not a tail function + I really can't tell what's going on during the return stage.
My current code:
long long int Factorial(int n)
{
if (n < 0)
return 0;
if (n == 0 || n == 1)
return 1;
return (n*Factorial(n - 1));
}
int DoubleFactorialTail(int n, int fact)
{
if (n < 0)
{
return 0;
}
if (n == 0 || n == 1)
{
return fact;
}
else
{
long long int factorial = Factorial(n);
return (factorial / DoubleFactorialTail(n - 1, fact));
}
}
I know that a double factorial tail-recursive function is supposed to call the recursive function at the end and nothing else, but here what I did was divide it by value(recursive in this case), that's why I'm not so sure my implementation is correct.
EDIT:
I originally tried implementing the following:
long long int DoubleFactorialTail(int n, int fact)
{
if (n < 0)
{
return 1;
}
if (n == 0 || n == 1)
{
return fact;
}
else
{
return (DoubleFactorialTail(n - 2, fact*n));
}
}
and the result will be:
res = (Factorial(n)/DoubleFactorialTail(n-1, 1));
Thing is, we were told that for n<0, the function needs to return 0 and save it in res.
but this equation will have 0 in its denominator if I choose to proceed and implement it this way.
So I guess my main question is: Is there a way to write this code in a tail-recursion manner while keeping this criterion intact?

I know that a double factorial tail-recursive function is supposed to call the recursive function at the end and nothing else
This is true, so
return (n*Factorial(n - 1));
or
return (factorial / DoubleFactorialTail(n - 1, fact));
Is not going to work.
The pattern has to be literally
return CallToRecursive(args);
The reason is that a tail recursive optimization lets CallToRecursive(args); return to the caller of this function and does not add a frame to the call-stack.
If you add code that needs to further process the return value, then it needs a frame in the call-stack to hold the return value and return point, and that's not TCO.
The way to approach this is usually to pass along work in progress to the next call.
long long int FactorialTCO(int n, long long factSoFar)
{
if (n < 0)
return 0;
if (n == 0 || n == 1)
return factSoFar;
return FactorialTCO(n - 1, n * factSoFar);
}
long long int Factorial(int n) {
return FactorialTCO(n, 1);
}
Note that this line:
return FactorialTCO(n - 1, n * factSoFar);
Returns exactly what it gets back from the recursive call. This means the compiler does not need to make a new stack frame, and that call will return to this function's caller. As we do this multiple times, we can effectively jump all the way back to the first caller when we are done instead of unwinding the stack frame.
I leave the transformation of the double up to you or others.

Related

why is this recursive function doesn't return 'counter' value?

int rec(int k)
{
static int temp = 0, counter = 0;
if(!k) return counter;
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
}
}
This function is supposed to get a number k and check how many operations are needed to get k to 0 only by multiplying by 2 or by adding 1.
this function works fine but returns zero instead of the last value in the counter. I tried to debug it, and I saw the counter value increasing, but after getting to the value it is supposed to return, the function goes back to complete all the calls, and returns 0.
I fixed it by making counter global and returning nothing, but my questions are:
Is there a way to fix it as it is with the counter inside the function?
Why is this function returning zero at the end?
Here's a nice recursive function that doesn't declare any variables at all, it's purely recursive!
int get_steps_to_zero(int n)
{
// Deal with negative values
if (n < 0) n *= -1;
if (n == 0) {
// Base case: we have reached zero
return 0;
} else if (n % 2 == 0) {
// Recursive case 1: we can divide by 2
return 1 + get_steps_to_zero(n / 2);
} else {
// Recursive case 2: we can subtract by 1
return 1 + get_steps_to_zero(n - 1);
}
}
get_steps_to_zero(457);
> 13
Others have addressed the general recursion issue, yet there remains a ...
Corner case
"this function works fine" --> Not quite.
The algorithm is an infinite loop for rec(-1) as it attempts -1 --> -2 --> -1 --> -2 ...
A better approach would sometimes add 1.
if(k%2) {
counter++;
// temp = rec(k-1);
temp = rec(k + (k < 0 ? 1 : -1));
}
This also well handles non-2's complement issue.
I will try to show a new side to this discussion,
Recursion is like a chain,
This means that any function can receive a value from its child and return a value to its parent.
In your program you are trying to return a value from the last child to the first parent,
So your program must have all links in the chain receive and send value in order.
But in your code you return a value only in the last call, and all other calls do not return this value back.
Your stop condition is here:
if(!k) return counter;
Only the last call enters this scope, but other calls do not reach any return statement.
they get to here:
if(k%2 == 0){
counter++;
temp = rec(k/2);
}
if(k%2){
counter++;
temp = rec(k-1);
here there is no return statement.
your compiler will warning you like this:
"warning: control reaches end of non-void function".
but your program will compile so it return zero like all non-void functions without return.
So if you want this program to work make it like Randomblock1, or like this:
int rec(int k)
{
static int counter = 0;
if(!k){
return counter;
}
else if(k%2 == 0){
counter ++;
counter += rec(k/2);
}
else{
counter++;
counter += rec(k-1);
}
return counter;
}
But this program also do not work well, what is the reason?
The reason is because you used by static variable.
It's a little hard to explain, but you can't use this recursion with a static variable, so add a patch to this line:
static int counter = 0;
like this
int counter = 0;
I hope what I wrote will be understandable

Why does this incorrect memoized fibonacci function work?

Here's an incorrect implementation of memoized fibonacci:
long int fib(int n) {
long int memo[100];
if(n<2) {
return n;
}
if(memo[n] != 0) {
return memo[n];
}
else {
memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
}
}
It is incorrect because the array memo is a brand new array each call and no memoization is occuring. The easiest fix is to make memo static. But, lo and behold, the code works!
I stepped through it in the debugger and memo is behaving as if it was static! It appears that the compiler generated code that is placing memo in the same memory space at every call as opposed to new fresh memory. Why is that?
Compiler used is Apple clang version 11.0.0 (clang-1100.0.33.12).
It is UB, but if we assume that stack of a fresh thread contains only zeroes,
then all values in memo[100] can be zeroes or remains of previous call of the function.
The effective algorithm might work like the following:
long int memo[100] = {0};
long int fib(int n) {
if(n<2) {
return n;
}
if(memo[n] != 0) {
return memo[n];
}
else {
memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
}
}
Except each layer of recursion have own 'memo[100]'.

how to determine whether number is even or odd using each function?

typedef int bool;
bool even(int n)
{
return odd(n-1);
}
bool odd(int n)
{
return even(n-1);
}
I am having difficulty understanding this code in C
1.Please explain why this definition is wrong.
2.correct this code and make even and odd call each other.
Thank you!
If you manually trace this code, you will quickly see that the functions will call each other an infinite number of times. They will never return. They will just keep calling each other forever.
This will surely lead to a "Stack Overflow". Which is the error that this site gets its name from!
As you know these two functions call each other recursively, but there is no condition to stop the calling each other and it goes infinitely. Hence you can modify your code likes the following:
typedef int bool;
bool even(int n)
{
if(n == 0)
return 1;
if(n == 1)
return 0;
return odd(n-1);
}
bool odd(int n)
{
if(n == 1)
return 1;
if(n == 0)
return 0;
return even(n-1);
}
For example follow odd(2). Their call each other likes the following:
odd(2) -> even(1) -> return 0
Or odd(7):
odd(7) -> even(6) -> odd(5) -> even(4) -> odd(3) -> even(2) -> odd(1) -> return 1
Hence if passing an odd number to the odd function, these recursive calling finished by 1 on odd function and the same for even function and vice versa for passing odd or even number to even and odd respectively.
2.correct this code and make even and odd call each other.
To answer just #2
// Better to use standard types and includes.
// typedef int bool;
#include <stdbool.h>
// declare before use
bool odd(int n);
// At most 2 recursive calls.
bool even(int n) {
// return odd(n-1);
return (n < -1 || n > 1) ? !odd(n) : n==0;
}
bool odd(int n) {
// return even(n-1);
return !even(n%2);
}
For those concerned about high probability, n & 1 fails as an odd() test with the wrong answer for negative values on 1's complement machines rusting away in the big-iron heaven
bool isOdd( int num )
{
return( num & 1 );
}
bool isEven( int num )
{
return( !(num & 1) );
}
the code snippet
bool even(int n) {
return odd(n-1);
}
And
bool odd(int n) {
return even(n-1);
}
your calling even() & odd() recursively and there is no terminating condition which results in stack overflow.
to check whether given number is even or odd, you have to check 0th bit status, if 0th bit is zero means its even number, if 0th bit is one(1) means its odd number at one stage.
Instead of this you can use bitwise logic if at all recursion is not compulsory.
bool even(int n) {
return n & 1; /*bitwise And, in all odd number 0th bit is set(1) */
}
Or if you want to do using recursion then put the base condition. for e.g
typedef int bool;
bool even_odd_method(int n) {
if(n<2) {
return n%2;
}
return even_odd_method(n-2);
}
int main(void) {
int number;
printf("\n enter the number \n");
scanf("%d",&number);
number = number > 0 ? number : -number;/*if input no is negative */
int ret1 = even_odd_method(number);
if(ret1 == 0) {
printf("even \n");
}
else {
printf("odd \n");
}
return 0;
}

Recursive function divide a number

I need to create a recursive function that receives a number by two without using /.
This is what I wrote, but it works only if after dividing it will still be a decimal number and not a float, that's why I asked.
int recursive(int a, int b){
if ( a == (0.5 * b) )
return a;
return recursive(a-1, b);
}
Btw, the function can receive only 1 parameter not 2 or more :/
I think you need something like this
int divide(int a, int b){
if(a - b <= 0){
return 1;
}
else {
return divide(a - b, b) + 1;
}
}
This divides by two using repeated subtraction and recursion.
int divide_by_two(int a) {
if (a < 0) return -divide_by_two(-a);
if (a < 2) return 0;
return 1 + divide_by_two(a - 2);
}
Generalising, this divides a by b using repeated subtraction and recursion.
int divide(int a, int b) {
if (a < 0) return -divide(-a, b);
if (b < 0) return -divide(a, -b);
if (a < b) return 0;
return 1 + divide(a - b, b);
}
Note, these functions don't round exactly the same way that division is defined to do in C.
You can try this, it should work:
int dividebytwo (int a){
static int answer = 0;
if (a < 0){
if ((answer * 2) > a){
answer --;
return dividebytwo (a);
}
return answer;
} else if (a > 0){
if ((answer * 2) < a){
answer ++;
return dividebytwo (a);
}
return answer;
}
return 0;
}
The trick here is using the static attribute. The static attribute means that the variable is only initialized once and retains its value after every function call. Really, you're using two parameters but it looks like you're only using one.
The only downside to this function is that you can only count on it to work more than once. Since this is probably for a simple homework assignment, it probably doesn't matter. But in reality, this is considered hugely inefficient and unreliable.
To compensate for the only-works-once factor, may add one of these fixes:
declare answer as a global variable and set it to 0 before every function call.
append return answer = 0; to the end of the function, instead of return 0;. This is so that whenever you want to call it again, you would call it beforehand as dividebytwo (0);.
I also cannot stress enough how weird of a concept this is, it sets of all sorts of red flags for anyone who practices careful programming - could be why you're getting so many downvotes. So use with caution!
#include<stdio.h>
int divide(int a, int b){
if( a-b < 0)
return 0;
else if ( a-b == 0)
return 1;
else {
return divide(a-b, b) + 1;
}
}
http://codepad.org/o4CoiaON

UVA's 3n+1 wrong answer although the test cases are correct . . .?

UVA problem 100 - The 3n + 1 problem
I have tried all the test cases and no problems are found.
The test cases I checked:
1 10 20
100 200 125
201 210 89
900 1000 174
1000 900 174
999999 999990 259
But why I get wrong answer all the time?
here is my code:
#include "stdio.h"
unsigned long int cycle = 0, final = 0;
unsigned long int calculate(unsigned long int n)
{
if (n == 1)
{
return cycle + 1;
}
else
{
if (n % 2 == 0)
{
n = n / 2;
cycle = cycle + 1;
calculate(n);
}
else
{
n = 3 * n;
n = n + 1;
cycle = cycle+1;
calculate(n);
}
}
}
int main()
{
unsigned long int i = 0, j = 0, loop = 0;
while(scanf("%ld %ld", &i, &j) != EOF)
{
if (i > j)
{
unsigned long int t = i;
i = j;
j = t;
}
for (loop = i; loop <= j; loop++)
{
cycle = 0;
cycle = calculate(loop);
if(cycle > final)
{
final = cycle;
}
}
printf("%ld %ld %ld\n", i, j, final);
final = 0;
}
return 0;
}
The clue is that you receive i, j but it does not say that i < j for all the cases, check for that condition in your code and remember to always print in order:
<i>[space]<j>[space]<count>
If the input is "out of order" you swap the numbers even in the output, when it is clearly stated you should keep the input order.
Don't see how you're test cases actually ever worked; your recursive cases never return anything.
Here's a one liner just for reference
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
Not quite sure how your code would work as you toast "cycle" right after calculating it because 'calculate' doesn't have explicit return values for many of its cases ( you should of had compiler warnings to that effect). if you didn't do cycle= of the cycle=calculate( then it might work?
and tying it all together :-
int three_n_plus_1(int n)
{
return n == 1 ? 1 : three_n_plus_1((n % 2 == 0) ? (n/2) : (3*n+1))+1;
}
int max_int(int a, int b) { return (a > b) ? a : b; }
int min_int(int a, int b) { return (a < b) ? a : b; }
int main(int argc, char* argv[])
{
int i,j;
while(scanf("%d %d",&i, &j) == 2)
{
int value, largest_cycle = 0, last = max_int(i,j);
for(value = min_int(i,j); value <= last; value++) largest_cycle = max_int(largest_cycle, three_n_plus_1(value));
printf("%d %d %d\r\n",i, j, largest_cycle);
}
}
Part 1
This is the hailstone sequence, right? You're trying to determine the length of the hailstone sequence starting from a given N. You know, you really should take out that ugly global variable. It's trivial to calculate it recursively:
long int hailstone_sequence_length(long int n)
{
if (n == 1) {
return 1;
} else if (n % 2 == 0) {
return hailstone_sequence_length(n / 2) + 1;
} else {
return hailstone_sequence_length(3*n + 1) + 1;
}
}
Notice how the cycle variable is gone. It is unnecessary, because each call just has to add 1 to the value computed by the recursive call. The recursion bottoms out at 1, and so we count that as 1. All other recursive steps add 1 to that, and so at the end we are left with the sequence length.
Careful: this approach requires a stack depth proportional to the input n.
I dropped the use of unsigned because it's an inappropriate type for doing most math. When you subtract 1 from (unsigned long) 0, you get a large positive number that is one less than a power of two. This is not a sane behavior in most situations (but exactly the right one in a few).
Now let's discuss where you went wrong. Your original code attempts to measure the hailstone sequence length by modifying a global counter called cycle. However, the main function expects calculate to return a value: you have cycle = calculate(...).
The problem is that two of your cases do not return anything! It is undefined behavior to extract a return value from a function that didn't return anything.
The (n == 1) case does return something but it also has a bug: it fails to increment cycle; it just returns cycle + 1, leaving cycle with the original value.
Part 2
Looking at the main. Let's reformat it a little bit.
int main()
{
unsigned long int i=0,j=0,loop=0;
Change these to long. By the way %ld in scanf expects long anyway, not unsigned long.
while (scanf("%ld %ld",&i,&j) != EOF)
Be careful with scanf: it has more return values than just EOF. Scanf will return EOF if it is not able to make a conversion. If it is able to scan one number, but not the second one, it will return 1. Basically a better test here is != 2. If scanf does not return two, something went wrong with the input.
{
if(i > j)
{
unsigned long int t=i;i=j;j=t;
}
for(loop=i;loop<=j;loop++)
{
cycle=0;
cycle=calculate(loop );
if(cycle>final)
{
final=cycle;
}
}
calculate is called hailstone_sequence_length now, and so this block can just have a local variable: { long len = hailstone_sequence_length(loop); if (len > final) final = len; }
Maybe final should be called max_length?
printf("%ld %ld %ld\n",i,j,final);
final=0;
final should be a local variable in this loop since it is separately used for each test case. Then you don't have to remember to set it to 0.
}
return 0;
}

Resources