package acts.act14;

/**
 * Examples for Tracing Recursion activity.
 *
 * @author CS159 Faculty
 * @version 11/18/2025
 */
public class RecursionTracing {

    /**
     * Find the number of bunny ears.
     *
     * @param bunnies number of bunnies
     * @return the number of ears for the bunnies
     */
    public static int bunnyEars(int bunnies) {
        if (bunnies == 0) {
            return 0;
        }
        return 2 + bunnyEars(bunnies - 1);
    }

    /**
     * Compute fibonacci sequence recursively.
     *
     * @param n fibonacci number to compute.
     * @return nth fibonacci number
     */
    public static int fibonacci(int n) {
        if (n == 0) {
            return 0;
        }
        if (n == 1) {
            return 1;
        }
        return fibonacci(n - 1) + fibonacci(n - 2);
    }

    /**
     * Are there any 6's? CodingBat array6.
     *
     * @param nums integer array to search
     * @param index current index being checked.
     * @return whether or not there is a 6.
     */
    public static boolean array6(int[] nums, int index) {
        if (nums.length == 0) {
            return false;
        }
        if (index == nums.length - 1) {
            return nums[index] == 6;
        }
        return (nums[index] == 6) || array6(nums, index + 1);
    }

    /**
     * Compute base to the power of n, recursively.
     *
     * @param base number to raise to a power
     * @param n power
     * @return base to power of n
     */
    public static int powerN(int base, int n) {
        if (n == 0) {
            return 1;
        }
        return base * powerN(base, n - 1);
    }

    /**
     * Count number of 7 digits in number.
     *
     * @param n number to count 7s in
     * @return number of 7s
     */
    public static int count7(int n) {
        if (n < 10) {
            if (n == 7) {
                return 1;
            } else {
                return 0;
            }
        }
        if (n % 10 == 7) {
            return 1 + count7(n / 10);
        } else {
            return count7(n / 10);
        }
    }

    /**
     * Computes "n choose k" recursively, known as the binomial coefficient.
     * https://en.wikipedia.org/wiki/Binomial_coefficient#Recursive_formula
     *
     * @param n how many to choose from
     * @param k how many to choose
     * @return the number of possibilities
     */
    public static int choose(int n, int k) {
        if (k == 0 || k == n) {
            return 1;
        }
        return choose(n - 1, k - 1) + choose(n - 1, k);
    }

    /**
     * Add all the digits in an integer number.
     *
     * @param n the number whose digits should be added up.
     * @return the sum of the digits
     */
    public static int challenge1(int n) {
        if (n == 0) {
            return 0;
        }
        int last = n % 10;
        return last + challenge1(n / 10);
    }

    /**
     * Change all c1 chars to c2, recursively.
     *
     * @param str string to change
     * @param c1 char to eliminate
     * @param c2 char to substitute
     * @return string with all c1 changed to c2
     */
    public static String challenge2(String str, char c1, char c2) {
        if (str.length() == 0) {
            return str;
        }
        if (str.charAt(0) == c1) {
            return c2 + challenge2(str.substring(1), c1, c2);
        }
        return str.charAt(0) + challenge2(str.substring(1), c1, c2);
    }

    /**
     * Count the number of integers equal to i2, in nums.
     *
     * @param nums array to count integers for
     * @param i1 index to start at
     * @param i2 integer to count
     * @return number of i2 in nums starting at i1
     */
    public static int challenge3(int[] nums, int i1, int i2) {
        if (i1 == nums.length) {
            return 0;
        }
        if (nums[i1] == i2) {
            return 1 + challenge3(nums, i1 + 1, i2);
        }
        return 0 + challenge3(nums, i1 + 1, i2);
    }

    /**
     * Test code output for recursion visualizations.
     *
     * @param args not used
     */
    public static void main(String[] args) {
        System.out.println("bunnyEars(3): " + bunnyEars(3));
        System.out.println("fibonacci(4): " + fibonacci(4));
        int[] nums = {6, 1, 7, 3};
        System.out.println("array6(nums, 0): " + array6(nums, 0));
        System.out.println("array6(nums, 2): " + array6(nums, 2));

        System.out.println("powerN(2, 3): " + powerN(2, 3));
        System.out.println("count7(1772): " + count7(1772));
        System.out.println("choose(4, 2): " + choose(4, 2));
        System.out.println("challenge1(345): " + challenge1(345));
        System.out.println(
                "challenge2(Hello, l, e): " + challenge2("Hello", 'l', 'e'));
        int[] nums2 = {12, 2, 12, 1, 3, 12};
        System.out.println(
                "challenge3(nums2, 0, 12): " + challenge3(nums2, 0, 12));
    }

}
