Hone logo
Hone
Problems

Tail Recursion Optimization in TypeScript

Tail recursion is a specific form of recursion where the recursive call is the very last operation performed in the function. Many functional programming languages optimize tail recursion into iterative loops, preventing stack overflow errors that can occur with deep recursion. This challenge asks you to implement a function that utilizes tail recursion and then demonstrates how to optimize it using a helper function to achieve the same result iteratively.

Problem Description

You are tasked with implementing a function factorialTailRecursive(n: number) that calculates the factorial of a non-negative integer n using tail recursion. Then, you must create a second function factorialIterative(n: number) that achieves the same result without recursion, effectively demonstrating the optimization of tail recursion. The iterative version should mimic the logic of the tail-recursive version.

What needs to be achieved:

  • Implement factorialTailRecursive(n) using tail recursion. This function should take a number n as input and return its factorial.
  • Implement factorialIterative(n) using an iterative approach (e.g., a for or while loop). This function should also take a number n as input and return its factorial.
  • Ensure both functions produce the same output for the same input.

Key Requirements:

  • factorialTailRecursive(n) must be tail-recursive. This means the recursive call must be the very last operation in the function.
  • factorialIterative(n) must be iterative and avoid recursion entirely.
  • Both functions must handle the base case of n = 0 correctly (factorial of 0 is 1).
  • Both functions must handle invalid input (negative numbers) gracefully. Return NaN if n is negative.

Expected Behavior:

  • For n = 0, both functions should return 1.
  • For n = 5, both functions should return 120.
  • For n = -1, both functions should return NaN.

Edge Cases to Consider:

  • n = 0 (base case)
  • n < 0 (invalid input)
  • Large values of n (potential for integer overflow, though this is not a primary focus of the challenge).

Examples

Example 1:

Input: 5
Output: 120
Explanation: 5! = 5 * 4 * 3 * 2 * 1 = 120

Example 2:

Input: 0
Output: 1
Explanation: 0! = 1 (by definition)

Example 3:

Input: -1
Output: NaN
Explanation: Factorial is not defined for negative numbers.

Constraints

  • n will be an integer.
  • n can be positive, negative, or zero.
  • The functions should be reasonably efficient. While performance optimization beyond tail recursion/iteration is not the primary focus, avoid unnecessary computations.
  • The iterative function should mimic the logic of the tail-recursive function.

Notes

  • Tail recursion optimization is not guaranteed in all JavaScript/TypeScript environments. The goal here is to demonstrate the concept of tail recursion and how it can be transformed into an iterative solution.
  • Think about how you can use an accumulator variable in the tail-recursive function to build up the factorial value.
  • The iterative function should use a loop to achieve the same result as the tail-recursive function with the accumulator.
  • Consider using Number.NaN to represent "Not a Number" for invalid input.
Loading editor...
typescript