Let's start from Binet's formula expressed in JavaScript:
const phi = (1 + Math.sqrt(5)) / 2;
const psi = (-1) / phi;
const fib = (n) => (phi ** n - psi ** n) / Math.sqrt(5);
We introduce a variable sr5
so we don't have to recompute the square root:
const sr5 = Math.sqrt(5);
const phi = (1 + sr5) / 2;
const psi = (-1) / phi;
const fib = (n) => (phi ** n - psi ** n) / sr5;
By inlining psi
we can write
const sr5 = Math.sqrt(5);
const phi = (1 + sr5) / 2;
const fib = (n) => (phi ** n - ((-1) / phi) ** n) / sr5;
which expands to
const sr5 = Math.sqrt(5);
const phi = (1 + sr5) / 2;
const fib = (n) => (phi ** n - (-1) ** n / phi ** n) / sr5;
When we look at the function only, we can extract the duplicate computation of phi
to the n
into a constant c
:
const fib = (n) => {
const c = phi ** n;
return (c - (-1) ** n / c) / sr5;
};
Let's also extract the exponentiation of -1 and since we need the negation of it, extract that negation as well:
const fib = (n) => {
const c = phi ** n;
const d = -((-1) ** n);
return (c + d / c) / sr5;
};
When we take a closer look at d
, we see that it is -1 for even values of n
and 1 for odd ones. So, n % 2
, which will give us either 0 or one, can be used instead of the exponentiation:
const d = n % 2 ? 1 : -1;
As the then branch of this expression equals the condition that leads to it, we can shorten this to
const d = n % 2 || -1;
By inlining d
again we get
const fib = (n) => {
const c = phi ** n;
return (c + (n % 2 || -1) / c) / sr5;
};
Now we want to zealously shorten the code replacing constant definitions by invocations of closures. Let's start with c
.
const fib = (n) => {
return (
(c) => (c + (n % 2 || -1) / c) / sr5
)(phi ** n);
};
Without the need for braces in the fib
function now and removing unnecessary parens we get
const sr5 = Math.sqrt(5);
const phi = (1 + sr5) / 2;
const fib = n => (c => (c + (n % 2 || -1) / c) / sr5)(phi ** n);
Let's use another closure accepting phi
as an argument and returning the actual fib
function:
const sr5 = Math.sqrt(5);
const fib = (phi =>
n => (c => (c + (n % 2 || -1) / c) / sr5)(phi ** n)
)((1 + sr5) / 2);
Doing the same again for the square root sr5
we get
const fib = (sr5 =>
(phi => n => (c => (c + (n % 2 || -1) / c) / sr5)(phi ** n))((1 + sr5) / 2)
)(Math.sqrt(5));
We can now shorten the variable names sr5
to a
and phi
to b
.
const fib = ( a => (b => n => (c => (c + (n % 2 || -1) / c) / a)(b ** n))((1 + a) / 2))(Math.sqrt(5));
Expressing the square root as 5 to the ½ and removing all whitespace we get the final definition:
const fib=(a=>(b=>n=>(c=>(c+(n%2||-1)/c)/a)(b**n))((1+a)/2))(5**.5);