0

The answer is probably blindingly obvious but for the life of me I can't see it. I am trying to find out how many iterations it takes for a user-supplied positive integer to converge to 1 (i.e. recursive function is f(x)=x/2 if x even, 3x+1 if x odd). The answer is trivial if done brute force (i.e. through a series of if statements). I am however aiming for a recursive approach, and am stuck in an infinite loop:

#include <stdio.h>

int collatz(long number, int length)    
{

    while (number != 1)
    {
        length++;
        printf("%ld\n", number);
        if ((number % 2) == 0)
            collatz(number/2,length);
        else
            collatz(3*number+1,length);
    }

    return length;
}
int main()  
{
    long number;
    printf("Input a number\n");
    scanf("%ld", &number);
    int length=1;
    printf("length is %d", collatz(number,length));
    return 0;
}

The problem occurs when number=1. Instead of the loop terminating, it continues and so it oscillates between 1 and 2 indefinitely.

andreithegiant
  • 215
  • 1
  • 10
  • 3
    I feel it's necessary to point out that this is not a good use of recursion. You had the right idea with the `while` loop. Instead of the recursive calls, just update the `number`, i.e. `number /= 2` and `number = 3*number+1`. – user3386109 May 06 '16 at 09:35

3 Answers3

3

The statement while (number != 1) will never evaluate to false, so you're stuck in an infinite loop whenever you pass number != 1.

As for computing the "length," you're passing by value, so the function won't compute the number of Collatz iterations needed to get to 1. Instead, just return one plus the number of Collatz iterations for the appropriate successor of the number. For example, the number of Collatz iterations required for a number n is 1 plus the number returned by a suitable recursive call, either on n/2 or 3*n+1, depending on whether n is even or odd, respectively.

This will work:

int collatz(long number)    
{
    if (number != 1)
    {
        printf("%ld\n", number);
        if ((number % 2) == 0)
            return 1+collatz(number/2);
        else
            return 1+collatz(3*number+1);
    }

    return 0;
}
blazs
  • 4,705
  • 24
  • 38
  • Thanks, I finally got it to work with an approach similar to yours. I still don't get why I never exit the loop. Taking input=8, for example, converges to 1 in 3 iterations, and gdb shows number=1 as well, but it will not exit the loop. – andreithegiant May 07 '16 at 05:24
  • You don't exit the loop because the variable `number` never changes because passing a _copy_ of `number` to a function. – blazs May 07 '16 at 09:26
0

I´m agree with @blazs. Notice that within the while loop you don´t actually modify the variable number so when the recursion rollback to the caller function, the while loop will evaluate the LOCAL copy of variable number again (which has not change) and then the while loop will keep going forever..

V.moreno
  • 44
  • 4
0

This works too, workaround to the scope problem of passing a copy of variables to the function:

    #include <stdio.h>

int collatz(long number, int length)    
{
    int temp=number;    
    int templength=length;  
    while (temp!= 1)
    {
        templength++;
        printf("%ld\n", number);
        if ((temp% 2) == 0)
            return collatz(temp/2,templength);
        else
            return collatz(3*temp+1,templength);
    }

    return templength;
}
int main()  
{
    long number;
    printf("Input a number\n");
    scanf("%ld", &number);
    int length=1;
    printf("length is %d", collatz(number,length));
    return 0;
}
andreithegiant
  • 215
  • 1
  • 10