'Possible to do a chained factorial method without a helper method
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);
Solution 1:[1]
Multiple mistakes here.
- Don't reassign
this.x, keep your instances immutable. - the
factorialmethod should not take a parameter, it should use the value stored in the instance - consequently, the recursive call of
factorialneeds to be made on a different instance, and not be given an argument - the
factorialmethod must always return a new instance, not nothing like your currentelsebranch.
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());
Solution 2:[2]
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…
Solution 3:[3]
I'm hoping this is only a proof-of-concept, and that you never plan on using code like this. But a simple change to your code will achieve this "through side-effects":
class InlineMath {
constructor(x) {
this.x = x
}
minus(y) {
this.x -= y;
return this;
}
times(y) {
this.x *= y;
return this;
}
factorial() {
if (this.x <= 1) {
this.x = 1;
} else {
this.x *= this.minus(1).factorial().x
}
return this;
}
}
const x = new InlineMath(3);
x.factorial().factorial();
console.log(x);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | |
| Solution 2 | |
| Solution 3 | Mulan |
