From 98ffd1d8d01f693ff733098dfa7120455b573be3 Mon Sep 17 00:00:00 2001 From: Fahim Faisaal Date: Sat, 26 Mar 2022 21:20:58 +0600 Subject: [PATCH 1/5] feat: added new validation test casses & methods --- Cache/LRUCache.js | 99 +++++++++++++++++++++++++++++++------ Cache/test/LRUCache.test.js | 43 +++++++++++++--- 2 files changed, 120 insertions(+), 22 deletions(-) diff --git a/Cache/LRUCache.js b/Cache/LRUCache.js index e416e03776..01890623db 100644 --- a/Cache/LRUCache.js +++ b/Cache/LRUCache.js @@ -1,39 +1,106 @@ class LRUCache { // LRU Cache to store a given capacity of data - constructor (capacity) { - this.cache = new Map() - this.capacity = capacity + #capacity + + constructor(capacity) { + if (!Number.isInteger(capacity) || capacity < 0) { + throw new TypeError('Invalid capacity') + } + + this.#capacity = ~~capacity + this.misses = 0 this.hits = 0 - this.miss = 0 + this.cache = new Map() + } + + get info() { + return Object.freeze({ + misses: this.misses, + hits: this.hits, + capacity: this.capacity, + size: this.size + }) + } + + get size() { + return this.cache.size + } + + get capacity() { + return this.#capacity + } + + /** + * delete oldest key existing in map by the help of iterator + */ + #removeLeastRecentlyUsed() { + this.cache.delete(this.cache.keys().next().value) + } + + set capacity(newCapacity) { + if (newCapacity < 0) { + throw new RangeError('Capacity should be greater than 0') + } + + if (newCapacity < this.capacity) { + let diff = this.capacity - newCapacity + + while (diff--) { + this.#removeLeastRecentlyUsed() + } + } + + this.#capacity = newCapacity } - cacheInfo () { - // Return the details for the cache instance [hits, misses, capacity, current_size] - return `CacheInfo(hits=${this.hits}, misses=${this.miss}, capacity=${this.capacity}, current size=${this.cache.size})` + has(key) { + key = String(key) + + return this.cache.has(key) } - set (key, value) { + set(key, value) { + key = String(key) // Sets the value for the input key and if the key exists it updates the existing key - if (this.cache.size === this.capacity) { - // delete oldest key existing in map - this.cache.delete(this.cache.keys().next().value) + if (this.size === this.capacity) { + this.#removeLeastRecentlyUsed() } + this.cache.set(key, value) } - get (key) { + get(key) { + key = String(key) // Returns the value for the input key. Returns null if key is not present in cache if (this.cache.has(key)) { const value = this.cache.get(key) + // refresh the cache to update the order of key this.cache.delete(key) this.cache.set(key, value) - this.hits += 1 + + this.hits++ return value - } else { - this.miss += 1 - return null } + + this.misses++ + return null + } + + toString(indent) { + const replacer = (_, value) => { + if (value instanceof Set) { + return [...value] + } + + if (value instanceof Map) { + return Object.fromEntries(value) + } + + return value + } + + return JSON.stringify(this, replacer, indent) } } diff --git a/Cache/test/LRUCache.test.js b/Cache/test/LRUCache.test.js index b03d609d66..cd409f258e 100644 --- a/Cache/test/LRUCache.test.js +++ b/Cache/test/LRUCache.test.js @@ -1,9 +1,19 @@ import { LRUCache } from '../LRUCache' import { fibonacciCache } from './cacheTest' -describe('LRUCache', () => { - it('Example 1 (Small Cache, size=2)', () => { - const cache = new LRUCache(2) +describe('Testing LRUCache', () => { + it("Testing with invalid capacity", () => { + expect(() => new LRUCache()).toThrow() + expect(() => new LRUCache('Invalid')).toThrow() + expect(() => new LRUCache(-1)).toThrow() + expect(() => new LRUCache(Infinity)).toThrow() + }) + + it('Example 1 (Small Cache, size = 2)', () => { + const cache = new LRUCache(1) // initially capacity + + cache.capacity++ // now the capacity is increasing by one + cache.set(1, 1) cache.set(2, 2) @@ -24,14 +34,35 @@ describe('LRUCache', () => { expect(cache.get(3)).toBe(3) expect(cache.get(4)).toBe(4) - expect(cache.cacheInfo()).toBe('CacheInfo(hits=6, misses=3, capacity=2, current size=2)') + expect(cache.info).toEqual({ + misses: 3, + hits: 6, + capacity: 2, + size: 2 + }) + + cache.capacity-- // now the capacity decreasing by one + + expect(cache.info).toEqual({ + misses: 3, + hits: 6, + capacity: 1, + size: 1 + }) }) - it('Example 2 (Computing Fibonacci Series, size=100)', () => { + it('Example 2 (Computing Fibonacci Series, size = 100)', () => { const cache = new LRUCache(100) + for (let i = 1; i <= 100; i++) { fibonacciCache(i, cache) } - expect(cache.cacheInfo()).toBe('CacheInfo(hits=193, misses=103, capacity=100, current size=98)') + + expect(cache.info).toEqual({ + misses: 103, + hits: 193, + capacity: 100, + size: 98 + }) }) }) From b8d6e686deb01499ac2d0bebd4bc022ff097c74a Mon Sep 17 00:00:00 2001 From: Fahim Faisaal Date: Sat, 26 Mar 2022 21:27:00 +0600 Subject: [PATCH 2/5] style: formated with standard --- Cache/LRUCache.js | 20 ++++++++++---------- Cache/test/LRUCache.test.js | 6 +++--- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Cache/LRUCache.js b/Cache/LRUCache.js index 01890623db..ae62ec33e5 100644 --- a/Cache/LRUCache.js +++ b/Cache/LRUCache.js @@ -2,7 +2,7 @@ class LRUCache { // LRU Cache to store a given capacity of data #capacity - constructor(capacity) { + constructor (capacity) { if (!Number.isInteger(capacity) || capacity < 0) { throw new TypeError('Invalid capacity') } @@ -13,7 +13,7 @@ class LRUCache { this.cache = new Map() } - get info() { + get info () { return Object.freeze({ misses: this.misses, hits: this.hits, @@ -22,22 +22,22 @@ class LRUCache { }) } - get size() { + get size () { return this.cache.size } - get capacity() { + get capacity () { return this.#capacity } /** * delete oldest key existing in map by the help of iterator */ - #removeLeastRecentlyUsed() { + #removeLeastRecentlyUsed () { this.cache.delete(this.cache.keys().next().value) } - set capacity(newCapacity) { + set capacity (newCapacity) { if (newCapacity < 0) { throw new RangeError('Capacity should be greater than 0') } @@ -53,13 +53,13 @@ class LRUCache { this.#capacity = newCapacity } - has(key) { + has (key) { key = String(key) return this.cache.has(key) } - set(key, value) { + set (key, value) { key = String(key) // Sets the value for the input key and if the key exists it updates the existing key if (this.size === this.capacity) { @@ -69,7 +69,7 @@ class LRUCache { this.cache.set(key, value) } - get(key) { + get (key) { key = String(key) // Returns the value for the input key. Returns null if key is not present in cache if (this.cache.has(key)) { @@ -87,7 +87,7 @@ class LRUCache { return null } - toString(indent) { + toString (indent) { const replacer = (_, value) => { if (value instanceof Set) { return [...value] diff --git a/Cache/test/LRUCache.test.js b/Cache/test/LRUCache.test.js index cd409f258e..c78ed70962 100644 --- a/Cache/test/LRUCache.test.js +++ b/Cache/test/LRUCache.test.js @@ -2,7 +2,7 @@ import { LRUCache } from '../LRUCache' import { fibonacciCache } from './cacheTest' describe('Testing LRUCache', () => { - it("Testing with invalid capacity", () => { + it('Testing with invalid capacity', () => { expect(() => new LRUCache()).toThrow() expect(() => new LRUCache('Invalid')).toThrow() expect(() => new LRUCache(-1)).toThrow() @@ -10,7 +10,7 @@ describe('Testing LRUCache', () => { }) it('Example 1 (Small Cache, size = 2)', () => { - const cache = new LRUCache(1) // initially capacity + const cache = new LRUCache(1) // initially capacity cache.capacity++ // now the capacity is increasing by one @@ -57,7 +57,7 @@ describe('Testing LRUCache', () => { for (let i = 1; i <= 100; i++) { fibonacciCache(i, cache) } - + expect(cache.info).toEqual({ misses: 103, hits: 193, From b7c961cc82e110eedfd6160bae25c57ec342886c Mon Sep 17 00:00:00 2001 From: Fahim Faisaal Date: Sat, 26 Mar 2022 21:41:43 +0600 Subject: [PATCH 3/5] feat: added parse method & test cases --- Cache/LRUCache.js | 13 +++++++++++++ Cache/test/LRUCache.test.js | 10 ++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/Cache/LRUCache.js b/Cache/LRUCache.js index ae62ec33e5..46f1d5b418 100644 --- a/Cache/LRUCache.js +++ b/Cache/LRUCache.js @@ -87,6 +87,19 @@ class LRUCache { return null } + parse (json) { + const { misses, hits, cache } = JSON.parse(json) + + this.misses += misses ?? 0 + this.hits += hits ?? 0 + + for (const key in cache) { + this.set(key, cache[key]) + } + + return this + } + toString (indent) { const replacer = (_, value) => { if (value instanceof Set) { diff --git a/Cache/test/LRUCache.test.js b/Cache/test/LRUCache.test.js index c78ed70962..d340dac010 100644 --- a/Cache/test/LRUCache.test.js +++ b/Cache/test/LRUCache.test.js @@ -41,11 +41,17 @@ describe('Testing LRUCache', () => { size: 2 }) + const json = '{"misses":3,"hits":6,"cache":{"3":3,"4":4}}' + expect(cache.toString()).toBe(json) + + // merge with json + cache.parse(json) + cache.capacity-- // now the capacity decreasing by one expect(cache.info).toEqual({ - misses: 3, - hits: 6, + misses: 6, + hits: 12, capacity: 1, size: 1 }) From 6b7b715696f2715b66fd626f9b9dcdcc570f21e4 Mon Sep 17 00:00:00 2001 From: Fahim Faisaal Date: Sun, 27 Mar 2022 06:52:48 +0600 Subject: [PATCH 4/5] docs: added js docs --- Cache/LRUCache.js | 40 +++++++++++++++++++++++++++++++++------- 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/Cache/LRUCache.js b/Cache/LRUCache.js index 46f1d5b418..71022ff56a 100644 --- a/Cache/LRUCache.js +++ b/Cache/LRUCache.js @@ -2,6 +2,10 @@ class LRUCache { // LRU Cache to store a given capacity of data #capacity + /** + * @param {number} capacity - the capacity of LRUCache + * @returns {LRUCache} - sealed + */ constructor (capacity) { if (!Number.isInteger(capacity) || capacity < 0) { throw new TypeError('Invalid capacity') @@ -11,6 +15,8 @@ class LRUCache { this.misses = 0 this.hits = 0 this.cache = new Map() + + return Object.seal(this) } get info () { @@ -30,13 +36,6 @@ class LRUCache { return this.#capacity } - /** - * delete oldest key existing in map by the help of iterator - */ - #removeLeastRecentlyUsed () { - this.cache.delete(this.cache.keys().next().value) - } - set capacity (newCapacity) { if (newCapacity < 0) { throw new RangeError('Capacity should be greater than 0') @@ -53,12 +52,27 @@ class LRUCache { this.#capacity = newCapacity } + /** + * delete oldest key existing in map by the help of iterator + */ + #removeLeastRecentlyUsed () { + this.cache.delete(this.cache.keys().next().value) + } + + /** + * @param {string} key + * @returns {*} + */ has (key) { key = String(key) return this.cache.has(key) } + /** + * @param {string} key + * @param {*} value + */ set (key, value) { key = String(key) // Sets the value for the input key and if the key exists it updates the existing key @@ -69,6 +83,10 @@ class LRUCache { this.cache.set(key, value) } + /** + * @param {string} key + * @returns {*} + */ get (key) { key = String(key) // Returns the value for the input key. Returns null if key is not present in cache @@ -87,6 +105,10 @@ class LRUCache { return null } + /** + * @param {JSON} json + * @returns {LRUCache} + */ parse (json) { const { misses, hits, cache } = JSON.parse(json) @@ -100,6 +122,10 @@ class LRUCache { return this } + /** + * @param {number} indent + * @returns {JSON} - string + */ toString (indent) { const replacer = (_, value) => { if (value instanceof Set) { From 269a3f4e4f8748f066c7ca1864f70758ac26b57a Mon Sep 17 00:00:00 2001 From: Fahim Faisaal Date: Sun, 27 Mar 2022 06:56:30 +0600 Subject: [PATCH 5/5] chore: added default import export --- Cache/LRUCache.js | 2 +- Cache/test/LRUCache.test.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cache/LRUCache.js b/Cache/LRUCache.js index 71022ff56a..d524bcbaec 100644 --- a/Cache/LRUCache.js +++ b/Cache/LRUCache.js @@ -143,4 +143,4 @@ class LRUCache { } } -export { LRUCache } +export default LRUCache diff --git a/Cache/test/LRUCache.test.js b/Cache/test/LRUCache.test.js index d340dac010..c9acc3dadf 100644 --- a/Cache/test/LRUCache.test.js +++ b/Cache/test/LRUCache.test.js @@ -1,4 +1,4 @@ -import { LRUCache } from '../LRUCache' +import LRUCache from '../LRUCache' import { fibonacciCache } from './cacheTest' describe('Testing LRUCache', () => { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy