Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 121 additions & 121 deletions Cache/LFUCache.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,210 +45,210 @@ class FrequencyMap extends Map {
}

class LFUCache {
#capacity
#frequencyMap
#capacity
#frequencyMap

/**
/**
* @param {number} capacity - The range of LFUCache
* @returns {LFUCache} - sealed
*/
constructor (capacity) {
this.#capacity = capacity
this.#frequencyMap = new FrequencyMap()
this.misses = 0
this.hits = 0
this.cache = new Map()

return Object.seal(this)
}
constructor (capacity) {
this.#capacity = capacity
this.#frequencyMap = new FrequencyMap()
this.misses = 0
this.hits = 0
this.cache = new Map()

return Object.seal(this)
}

/**
/**
* Get the capacity of the LFUCache
* @returns {number}
*/
get capacity () {
return this.#capacity
}
get capacity () {
return this.#capacity
}

/**
/**
* Get the current size of LFUCache
* @returns {number}
*/
get size () {
return this.cache.size
}
get size () {
return this.cache.size
}

/**
/**
* Set the capacity of the LFUCache if you decrease the capacity its removed CacheNodes following the LFU - least frequency used
*/
set capacity (newCapacity) {
if (this.#capacity > newCapacity) {
let diff = this.#capacity - newCapacity // get the decrement number of capacity
set capacity (newCapacity) {
if (this.#capacity > newCapacity) {
let diff = this.#capacity - newCapacity // get the decrement number of capacity

while (diff--) {
this.#removeCacheNode()
}

this.cache.size === 0 && this.#frequencyMap.clear()
while (diff--) {
this.#removeCacheNode()
}

this.#capacity = newCapacity
this.cache.size === 0 && this.#frequencyMap.clear()
}

get info () {
return Object.freeze({
misses: this.misses,
hits: this.hits,
capacity: this.capacity,
currentSize: this.size,
leastFrequency: this.leastFrequency
})
}
this.#capacity = newCapacity
}

get leastFrequency () {
const freqCacheIterator = this.#frequencyMap.keys()
let leastFrequency = freqCacheIterator.next().value || null
get info () {
return Object.freeze({
misses: this.misses,
hits: this.hits,
capacity: this.capacity,
currentSize: this.size,
leastFrequency: this.leastFrequency
})
}

// select the non-empty frequency Set
while (this.#frequencyMap.get(leastFrequency)?.size === 0) {
leastFrequency = freqCacheIterator.next().value
}
get leastFrequency () {
const freqCacheIterator = this.#frequencyMap.keys()
let leastFrequency = freqCacheIterator.next().value || null

return leastFrequency
// select the non-empty frequency Set
while (this.#frequencyMap.get(leastFrequency)?.size === 0) {
leastFrequency = freqCacheIterator.next().value
}

#removeCacheNode () {
const leastFreqSet = this.#frequencyMap.get(this.leastFrequency)
// Select the least recently used node from the least Frequency set
const LFUNode = leastFreqSet.values().next().value
return leastFrequency
}

leastFreqSet.delete(LFUNode)
this.cache.delete(LFUNode.key)
}
#removeCacheNode () {
const leastFreqSet = this.#frequencyMap.get(this.leastFrequency)
// Select the least recently used node from the least Frequency set
const LFUNode = leastFreqSet.values().next().value

leastFreqSet.delete(LFUNode)
this.cache.delete(LFUNode.key)
}

/**
/**
* if key exist then return true otherwise false
* @param {any} key
* @returns {boolean}
*/
has (key) {
key = String(key) // converted to string
has (key) {
key = String(key) // converted to string

return this.cache.has(key)
}
return this.cache.has(key)
}

/**
/**
* @method get
* @description - This method return the value of key & refresh the frequencyMap by the oldNode
* @param {string} key
* @returns {any}
*/
get (key) {
key = String(key) // converted to string
get (key) {
key = String(key) // converted to string

if (this.cache.has(key)) {
const oldNode = this.cache.get(key)
this.#frequencyMap.refresh(oldNode)
if (this.cache.has(key)) {
const oldNode = this.cache.get(key)
this.#frequencyMap.refresh(oldNode)

this.hits++
this.hits++

return oldNode.value
}

this.misses++
return null
return oldNode.value
}

/**
this.misses++
return null
}

/**
* @method set
* @description - This method stored the value by key & add frequency if it doesn't exist
* @param {string} key
* @param {any} value
* @param {number} frequency
* @returns {LFUCache}
*/
set (key, value, frequency = 1) {
key = String(key) // converted to string
set (key, value, frequency = 1) {
key = String(key) // converted to string

if (this.#capacity === 0) {
throw new RangeError('LFUCache ERROR: The Capacity is 0')
}
if (this.#capacity === 0) {
throw new RangeError('LFUCache ERROR: The Capacity is 0')
}

if (this.cache.has(key)) {
const node = this.cache.get(key)
node.value = value
if (this.cache.has(key)) {
const node = this.cache.get(key)
node.value = value

this.#frequencyMap.refresh(node)
this.#frequencyMap.refresh(node)

return this
}
return this
}

// if the cache size is full, then it's delete the Least Frequency Used node
if (this.#capacity === this.cache.size) {
this.#removeCacheNode()
}
// if the cache size is full, then it's delete the Least Frequency Used node
if (this.#capacity === this.cache.size) {
this.#removeCacheNode()
}

const newNode = new CacheNode(key, value, frequency)
const newNode = new CacheNode(key, value, frequency)

this.cache.set(key, newNode)
this.#frequencyMap.insert(newNode)
this.cache.set(key, newNode)
this.#frequencyMap.insert(newNode)

return this
}
return this
}

/**
/**
* @method parse
* @description - This method receive a valid LFUCache JSON & run JSON.prase() method and merge with existing LFUCache
* @param {JSON} json
* @returns {LFUCache} - merged
*/
parse (json) {
const { misses, hits, cache } = JSON.parse(json)
parse (json) {
const { misses, hits, cache } = JSON.parse(json)

this.misses += misses ?? 0
this.hits += hits ?? 0
this.misses += misses ?? 0
this.hits += hits ?? 0

for (const key in cache) {
const { value, frequency } = cache[key]
this.set(key, value, frequency)
}

return this
for (const key in cache) {
const { value, frequency } = cache[key]
this.set(key, value, frequency)
}

/**
return this
}

/**
* @method clear
* @description - This method cleared the whole LFUCache
* @returns {LFUCache}
*/
clear () {
this.cache.clear()
this.#frequencyMap.clear()
clear () {
this.cache.clear()
this.#frequencyMap.clear()

return this
}
return this
}

/**
/**
* @method toString
* @description - This method generate a JSON format of LFUCache & return it.
* @param {number} indent
* @returns {string} - JSON
*/
toString (indent) {
const replacer = (_, value) => {
if (value instanceof Set) {
return [...value]
}

if (value instanceof Map) {
return Object.fromEntries(value)
}
toString (indent) {
const replacer = (_, value) => {
if (value instanceof Set) {
return [...value]
}

return value
if (value instanceof Map) {
return Object.fromEntries(value)
}

return JSON.stringify(this, replacer, indent)
return value
}

return JSON.stringify(this, replacer, indent)
}
}

export default LFUCache
2 changes: 1 addition & 1 deletion Maths/CollatzSequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ export function collatz (n) {
steps.push(n)
}

return { result: n, steps: steps }
return { result: n, steps }
}
Loading