Write a function that makes another function remember its results.
What to build
memoize(fn), which returns a version of fn that only does the work the first time it sees a value.
Requirements
- The starter counts how many times
squarereally runs. - Complete
memoize(fn)so that the function it returns stores each result, and returns the stored result when the same argument appears again. - Do not change the rest of the program.
Input
Several lines, each a whole number.
Output
One line for each number, and then the total number of real calls. The starter prints these for you.
Constraints
There are from 1 to 100 numbers, from -1000 to 1000.
Example
Input:
2
3
2
Output:
2 -> 4 (computed)
3 -> 9 (computed)
2 -> 4 (cached)
calls: 2
Why it works
The Map lives in memoize's scope, so it survives between calls and nothing else can reach it. Checking with has matters because a stored answer can be 0, which is falsy.
Examples
2 3 2
2 -> 4 (computed) 3 -> 9 (computed) 2 -> 4 (cached) calls: 2
5 5 5
5 -> 25 (computed) 5 -> 25 (cached) 5 -> 25 (cached) calls: 1
Hints
Hint 1
memoize creates one Map, and returns a function that can see it.
Hint 2
Use cache.has(x), not cache.get(x), because a stored result can be 0.
Hint 3
If the Map has no answer yet, call fn(x), store the result and return it.
Solution
Show one correct solution (try it yourself first)
let calls = 0;
function square(x) {
calls++;
return x * x;
}
function memoize(fn) {
const cache = new Map();
return (x) => {
if (!cache.has(x)) {
cache.set(x, fn(x));
}
return cache.get(x);
};
}
const fast = memoize(square);
let line = prompt();
while (line !== null) {
const x = Number(line);
const before = calls;
const result = fast(x);
console.log(`${x} -> ${result} ${calls > before ? "(computed)" : "(cached)"}`);
line = prompt();
}
console.log(`calls: ${calls}`);