Factorial Generator

Updated on 27 May, 2025
Factorial Generator header image

Problem Statement

In the problem, the task is to create a generator function named factorial that accepts an integer parameter n. This generator should yield values sequentially that form the factorial sequence up to n. The factorial sequence is essentially a series of products calculated from the input integer down to 1. Specifically, for a number n, its factorial (denoted as n!) is the product of all positive integers less than or equal to n.

Given this, the factorial of 0 (0!) is a special case which is defined as 1. Your function will start yielding from 1!, progressing through 2!, 3!, and so on until it reaches n!.

Examples

Example 1

Input:

n = 5

Output:

[1,2,6,24,120]

Explanation:

const gen = factorial(5)
gen.next().value // 1
gen.next().value // 2
gen.next().value // 6
gen.next().value // 24
gen.next().value // 120

Example 2

Input:

n = 2

Output:

[1,2]

Explanation:

const gen = factorial(2)
gen.next().value // 1
gen.next().value // 2

Example 3

Input:

n = 0

Output:

[1]

Explanation:

const gen = factorial(0)
gen.next().value // 1

Constraints

  • 0 <= n <= 18

Approach and Intuition

The function must generate each factorial in sequence up to the nth factorial. Here is a step-by-step breakdown based on the examples provided:

  1. Initialize current_factorial to 1 (since 1! = 1).
  2. Use a loop that iterates from 1 to n.
    • On each iteration:
      • Multiply the current_factorial by the current loop index.
      • Yield the updated current_factorial.
  3. For the input value of n = 0, directly yield 1, as 0! = 1.

Examining the constraints and examples:

  • For n = 5: The outputs are [1, 2, 6, 24, 120]. This sequence is the result of computing the factorial for each integer from 1 to 5.
    • 1! = 1
    • 2! = 1 * 2 = 2
    • 3! = 1 * 2 * 3 = 6
    • 4! = 1 * 2 * 3 * 4 = 24
    • 5! = 1 * 2 * 3 * 4 * 5 = 120
  • For n = 2: The sequence [1, 2] corresponds to the factorials of 1 and 2.
  • For n = 0: It simply yields [1], corresponding to 0!.

From this, it's evident that the generator approach efficiently calculates each factorial only once and on-demand, conserving memory and processing resources, especially critical since the factorial values grow very fast with increasing n, although here it is capped at 18, which is manageable.

Solutions

  • JavaScript
js
function* factorialGenerator(limit) {
    const cache = new Map();

    function computeFactorial(x) {
        if (cache.has(x)) {
            return cache.get(x);
        }

        let output;
        if (x <= 1) {
            output = 1;
        } else {
            output = x * computeFactorial(x - 1);
        }

        cache.set(x, output);
        return output;
    }

    if (limit === 0) {
        yield 1;
    } else {
        for (let j = 1; j <= limit; j++) {
            yield computeFactorial(j);
        }
    }
}

The provided JavaScript code implements a generator function named factorialGenerator that efficiently computes factorials up to a specified limit using recursion and memoization.

  • This function utilizes a generator to yield factorial values one by one, which is useful for handling large sequences of factorials without loading them all into memory at once.
  • Memoization is implemented using a Map object named cache. This stores previously computed factorial values to avoid redundant calculations, speeding up the function especially for higher numbers.
  • The computeFactorial function is a recursive inner function responsible for the actual computation of factorial values. It checks if the result for the current number x exists in cache:
    • If it does, the cached value is returned.
    • If not, it computes the factorial by recursive multiplication, stores this result in the cache, and then returns the result.
  • The main factorialGenerator function checks if the limit is 0, yielding 1 directly since 0! is 1. Otherwise, it iterates from 1 to limit, using the computeFactorial function to yield each factorial result.

Use this generator function by initializing it with a limit and then iterating over it to retrieve factorial values up to and including that limit. This approach not only optimizes performance with memoization but also utilizes the generator's lazy evaluation property, making it efficient for computing large factorial values in a resource-constrained environment.

Comments

No comments yet.