Home > Mobile >  Possible to do a chained factorial method without a helper method
Possible to do a chained factorial method without a helper method

Time:01-20

I'm seeing if it's possible to write a factorial method as follows:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial(n) {
        if (n == 1) {
            return this;
        } else {
            this.x = this.times(this.factorial(this.minus(1)));
        }
    }
}
x = new InlineMath(2);
x.factorial().factorial();
console.log(x);

I know this is a totally non-standard way to do it but was just seeing if this way was possible (i.e., only through side-effects).

But so far the only way I can figure out how to do it is offload it like so:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial() {
        this.x = _factorial(this.x);
        return this;
    }
}
function _factorial(n) {
    if (n==1) {
        return n;
    } else {
        return n * _factorial(n-1);
    }  
}
x = new InlineMath(2);
x.factorial().factorial();
console.log(x);

CodePudding user response:

Multiple mistakes here.

  • Don't reassign this.x, keep your instances immutable.
  • the factorial method should not take a parameter, it should use the value stored in the instance
  • consequently, the recursive call of factorial needs to be made on a different instance, and not be given an argument
  • the factorial method must always return a new instance, not nothing like your current else branch.

With some renaming:

class InlineNumber {
    constructor(n) {
        this.n = n
    }
    factorial() {
        if (this.n == 1) {
            // return 1
            return this;
        } else {
            // return n * (n-1)!
            return this.times(this.minus(new InlineNumber(1)).factorial());
        }
    }
    minus(subtrahend) {
        return new InlineNumber(this.n - subtrahend.n);
    }
    times(multiplicand) {
        return new InlineNumber(this.n * multiplicand.n);
    }
    valueOf() {
        return this.n;
    }
}
const x = new InlineNumber(3);
console.log(x.factorial().factorial());

CodePudding user response:

In the factorial formula n * (n-1)!, you need the value n twice. With a mutable math object, you'll need to clone it for the recursive call:

class InlineMath {
    constructor(x) {
        this.x = x
    }
    clone() {
        return new InlineMath(this.x);
    }
    minus(y) {
        this.x -= y;
        return this;
    }
    times(y) {
        this.x *= y;
        return this;
    }
    factorial() {
        if (this.x > 1)
            this.times(this.clone().minus(1).factorial().x);
        return this;
    }
}
x = new InlineMath(3);
x.factorial().factorial();
console.log(x);

Notice that writing the formula as (n-1)! * n is not easily possible:

this.minus(1).factorial().times(this.clone().x)

won't work as the cloning happens too late. I recommend my other answer which avoids this can of worms…

  •  Tags:  
  • Related