From 028e098b63bbf8f5ed46eedbaa38d09c28202db4 Mon Sep 17 00:00:00 2001 From: Damien Chazoule Date: Mon, 4 Oct 2021 13:40:17 +0200 Subject: [PATCH 1/4] Feat: Added Memoize Func --- Cache/Memoize.js | 29 ++++++++++++++++++++++++++ Cache/__tests__/Memoize.test.js | 37 +++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 Cache/Memoize.js create mode 100644 Cache/__tests__/Memoize.test.js diff --git a/Cache/Memoize.js b/Cache/Memoize.js new file mode 100644 index 000000000..932b6187c --- /dev/null +++ b/Cache/Memoize.js @@ -0,0 +1,29 @@ +/** + * Memoize + * @param {Function} fn + * @returns + */ +export const memoize = (func) => { + // eslint-disable-next-line no-console + console.log(`Creating cache for function '${func.name}'`) + + const cache = {} + + return (...args) => { + const [arg] = args + + if (arg in cache) { + // eslint-disable-next-line no-console + console.log(`Reading cache with argument ${arg}`) + + return cache[arg] + } + + // eslint-disable-next-line no-console + console.log(`Updating cache with argument ${arg}`) + + const result = func(arg) + cache[arg] = result + return result + } +} diff --git a/Cache/__tests__/Memoize.test.js b/Cache/__tests__/Memoize.test.js new file mode 100644 index 000000000..74f3f5762 --- /dev/null +++ b/Cache/__tests__/Memoize.test.js @@ -0,0 +1,37 @@ +import { memoize } from '../Memoize' + +const fibonacci = (n) => { + if (n < 2) { + return n + } + + return fibonacci(n - 2) + fibonacci(n - 1) +} + +const factorial = (n) => { + if (n === 0) { + return 1 + } + + return n * factorial(n - 1) +} + +describe('memoize', () => { + it('expects the fibonacci function to use the cache on the second call', () => { + const memoFibonacci = memoize(fibonacci) + + expect(memoFibonacci(5)).toEqual(fibonacci(5)) + expect(memoFibonacci(5)).toEqual(5) + expect(memoFibonacci(10)).toEqual(fibonacci(10)) + expect(memoFibonacci(10)).toEqual(55) + }) + + it('expects the factorial function to use the cache on the second call', () => { + const memoFactorial = memoize(factorial) + + expect(memoFactorial(5)).toEqual(factorial(5)) + expect(memoFactorial(5)).toEqual(120) + expect(memoFactorial(10)).toEqual(factorial(10)) + expect(memoFactorial(10)).toEqual(3_628_800) + }) +}) From c8fd5353ba2c90d79a1b954c0f525baecc640a10 Mon Sep 17 00:00:00 2001 From: Damien Chazoule Date: Mon, 4 Oct 2021 14:15:21 +0200 Subject: [PATCH 2/4] Updating Memoize Unit Test --- Cache/__tests__/Memoize.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cache/__tests__/Memoize.test.js b/Cache/__tests__/Memoize.test.js index 74f3f5762..4d156ce34 100644 --- a/Cache/__tests__/Memoize.test.js +++ b/Cache/__tests__/Memoize.test.js @@ -16,7 +16,7 @@ const factorial = (n) => { return n * factorial(n - 1) } -describe('memoize', () => { +describe('Memoize', () => { it('expects the fibonacci function to use the cache on the second call', () => { const memoFibonacci = memoize(fibonacci) @@ -32,6 +32,6 @@ describe('memoize', () => { expect(memoFactorial(5)).toEqual(factorial(5)) expect(memoFactorial(5)).toEqual(120) expect(memoFactorial(10)).toEqual(factorial(10)) - expect(memoFactorial(10)).toEqual(3_628_800) + expect(memoFactorial(10)).toEqual(3628800) }) }) From 8bce33d2659e101c79fd33e70caca66db6770dc0 Mon Sep 17 00:00:00 2001 From: Damien Chazoule Date: Tue, 5 Oct 2021 08:50:12 +0200 Subject: [PATCH 3/4] Moving '__tests__' To 'test' --- Cache/Memoize.js | 12 +++--------- Cache/{__tests__ => test}/Memoize.test.js | 0 2 files changed, 3 insertions(+), 9 deletions(-) rename Cache/{__tests__ => test}/Memoize.test.js (100%) diff --git a/Cache/Memoize.js b/Cache/Memoize.js index 932b6187c..36309cbb3 100644 --- a/Cache/Memoize.js +++ b/Cache/Memoize.js @@ -4,24 +4,18 @@ * @returns */ export const memoize = (func) => { - // eslint-disable-next-line no-console - console.log(`Creating cache for function '${func.name}'`) - + // Initializing new cache const cache = {} return (...args) => { const [arg] = args if (arg in cache) { - // eslint-disable-next-line no-console - console.log(`Reading cache with argument ${arg}`) - + // Reading cache by argument return cache[arg] } - // eslint-disable-next-line no-console - console.log(`Updating cache with argument ${arg}`) - + // Updating cache by argument const result = func(arg) cache[arg] = result return result diff --git a/Cache/__tests__/Memoize.test.js b/Cache/test/Memoize.test.js similarity index 100% rename from Cache/__tests__/Memoize.test.js rename to Cache/test/Memoize.test.js From 0589fc19e0d18b43f65b315d7b99976503594df6 Mon Sep 17 00:00:00 2001 From: Damien Chazoule Date: Tue, 5 Oct 2021 10:37:14 +0200 Subject: [PATCH 4/4] Added comments about memoization --- Cache/Memoize.js | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/Cache/Memoize.js b/Cache/Memoize.js index 36309cbb3..9bd998fda 100644 --- a/Cache/Memoize.js +++ b/Cache/Memoize.js @@ -1,21 +1,40 @@ /** * Memoize - * @param {Function} fn - * @returns + * + * From [Wikipedia](https://en.wikipedia.org/wiki/Memoization), + * memoization is an optimization technique + * used primarily to speed up computer programs, + * by storing the results of expensive function calls + * and returning the cached result when the same inputs occur again + * + * This function is a first class objects, + * which lets us use it as [Higher-Order Function](https://eloquentjavascript.net/05_higher_order.html) + * and return another function + * + * @param {Function} func Original function + * @returns {Function} Memoized function */ export const memoize = (func) => { - // Initializing new cache + // Initialization of a slot to store the function result const cache = {} return (...args) => { + // Retrieving the first argument of the function const [arg] = args + /** + * Checks if the argument is already present in the cache, + * then return the associated value / result + */ if (arg in cache) { - // Reading cache by argument return cache[arg] } - // Updating cache by argument + /** + * If the argument is not yet present in the cache, + * execute original function and save its value / result in cache, + * finally return it + */ const result = func(arg) cache[arg] = result return result