0

I'm trying to understand recursion with Java better and I'm doing a program which ist using iteration, head and tail recursion.It should count how many times does the different methods called. What should I add to the head and to the tail part to complete the program? Thank you in advance

public class Recursion {
    public static void main(String[] args) {
        System.out.println("Test fibonacci: 0 = 0");
        System.out.println("iterativ: " + fibIt(0));
        System.out.println("head: " + fibHr(0));
        System.out.println("tail: " + fibTr(0));

        System.out.println("\nTest fibonacci: 5 = 5");
        System.out.println("iterativ: " + fibIt(5));
        System.out.println("head: " + fibHr(5));
        System.out.println("tail: " + fibTr(5));

        System.out.println("\nTest fibonacci: 10 = 55");
        System.out.println("iterativ: " + fibIt(10));
        System.out.println("head: " + fibHr(10));
        System.out.println("tail: " + fibTr(10));
    }

    private static int fibIt(int n) {
        switch (n) {
            case 0:
                return 0;
            case 1:
                return 1;
        }

        int a = 0;
        int b = 1;

        for (int i = 2; i <= n; i++) {
            b = a + b;
            a = b - a;
        }

        return b;
    }

    private static int fibHr(int n) {
        int counter = 0;
        switch (n) {
            case 0:
                counter +=1;
                return 0; 
            case 1:
                counter += 1;
                return 1;
            default:
                counter = counter +1;
                return fibHr(n - 1) + fibHr(n - 2) ;    
        }
    }

    private static int fibTr(int n) {
        return fibTr(0, 1, n);
    }

    private static int fibTr(int a, int b, int n) {
        switch (n) {
            case 0:
                return a;
            case 1:
                return b;
            default:
                return fibTr(b, a + b, n - 1);
        }
    }    
}

How can I get the counter value in the head recursion? I have tried everything to print it out but I have no clue how does it work. I would like to count the number of returns I have tried System.out.print but I simply got a huge number of 1-s.

knittl
  • 246,190
  • 53
  • 318
  • 364
  • 1
    What do you want to complete? All methods already return the the same result for identical inputs. (but none of your methods is called by your program) – knittl Jan 25 '22 at 18:22
  • I just want to Extend the recursive methods fibHr and fibTr so that they count how often they are called. I don't know how could I do it –  Jan 25 '22 at 18:24
  • 1
    Ah, I missed that part. Depends on what your state is and when you want to reset your counters. You could create a `private static long` field to your class and increment it from your methods. Or wrap each method in a class with state (= the counter) – knittl Jan 25 '22 at 18:26
  • Could u maybe help to me how does it work? wrap each method in a class with state (= the counter). I'm pretty much in beginner in this topics –  Jan 25 '22 at 18:27
  • 1
    Java may not do what you want regarding `tail recursion`. See [Does java support and optimize away tail recursive calls](https://stackoverflow.com/questions/20826786/does-java-support-and-optimize-away-tail-recursive-calls) – WJS Jan 25 '22 at 20:40

1 Answers1

1

You can convert each method to an instance method of a class which then holds the counter in a private field, with a getter to expose the value.

public class HeadRecursion {
  private long counter = 0;
  public int fib(int n) {
    ++counter;
    switch (n) {
        case 0:
            return 0;
        case 1:
            return 1;
        default:
            return fibHr(n - 1) + fibHr(n - 2);
    }
  }
  public long getCounter() { return count; }
}

Then you can instantiate your class, run your function and then get and output the counter:

public static void main() {
  final var obj = new HeadRecursion();
  final var number = obj.fib(10);
  System.out.println(number);
  System.out.println(obj.getCounter());
}

Note that the counter must be a field declared in the class and not a local variable defined inside the method due to at least two reasons:

  • A local variable is not visible nor accessible outside its scope, i.e. the enclosing function
  • Every time the function is called, the variable would be re-initialized. Each recursive call would start with the original value of the variable again.
knittl
  • 246,190
  • 53
  • 318
  • 364
  • and could you please help me also with the tail recursion? –  Jan 25 '22 at 18:37
  • @Herrpeter simply create a new class and put your tail recursive method there – knittl Jan 25 '22 at 18:39
  • can I just simply copy paste this code above? It doesn't work to me –  Jan 25 '22 at 20:37
  • @Herrpeter What does not work? What error does it give? If there's no error, what is the actual vs. expected output? "does not work" is not helpful – knittl Jan 25 '22 at 20:41
  • your solution is for sure excellent but I don't get it I have edited my question. In the head recursion I try to give out the counter but it doesn't work. –  Jan 25 '22 at 20:49
  • @Herrpeter I don't understand. You state that my code does not work, but then you go on and explain that other code "does not work". Which one is it? Does the proposed code from the answer not work or does another, non-answer code not work? – knittl Jan 25 '22 at 20:58
  • I don't understand your code at all sorry. I tried to solve it on my own, it gives out the right value to the head and tail recursion also, but I don't know how to give out the counter value to the head recursion(fibHr). I really appreciate your help a lot. –  Jan 25 '22 at 21:02
  • 1
    The code defines a class with data (the counter) and behavior (the fibonacci method). Creating an object from a class with `new` gives you an independent instance of this class. You can then use this instance to call methods on it, which potentially update the state of the object; in this case the counter. By implementing a simple getter, the state can be queried from anything with a reference to the object instance. The other two classes can be implemented similarly, only the method body of `fib` will be different. – knittl Jan 25 '22 at 21:07
  • @Herrpeter I'm having difficulties answering because I don't understand which part of the answer confuses you exactly. Is it classes, objects, methods, fields, getters, or variables? Or is it instance vs static members? Is it calling methods or instantiating class instances, i.e. objects? Is it recursion itself? – knittl Jan 25 '22 at 22:01