From a93f524fd0fad04b3b315f2b7669d27a1bd5d19b Mon Sep 17 00:00:00 2001 From: Zhenya Zasko Date: Thu, 17 Jan 2019 00:17:29 +0200 Subject: [PATCH] Make tasks --- JavaScript/8-timerMemoize.js | 35 ++++++ JavaScript/9-countMemoize.js | 49 ++++++++ JavaScript/a-sizeMemoize.js | 93 +++++++++++++++ JavaScript/b-syncAsyncMemoize.js | 53 +++++++++ JavaScript/c-memoizeUnity.js | 198 +++++++++++++++++++++++++++++++ 5 files changed, 428 insertions(+) create mode 100644 JavaScript/8-timerMemoize.js create mode 100644 JavaScript/9-countMemoize.js create mode 100644 JavaScript/a-sizeMemoize.js create mode 100644 JavaScript/b-syncAsyncMemoize.js create mode 100644 JavaScript/c-memoizeUnity.js diff --git a/JavaScript/8-timerMemoize.js b/JavaScript/8-timerMemoize.js new file mode 100644 index 0000000..264f0e9 --- /dev/null +++ b/JavaScript/8-timerMemoize.js @@ -0,0 +1,35 @@ +'use strict'; + +const argKey = x => (x.toString() + ':' + typeof(x)); +const generateKey = arg => arg.map(argKey).join('|'); + +const timerMemoize = (fn, msec) => { + const cache = new Map(); + return (...args) => { + const key = generateKey(args); + const timeout = setTimeout(() => cache.delete(key), msec); + if (cache.has(key)) { + const value = cache.get(key); + console.log('From cache: ', value.res); + clearTimeout(value.timeout); + value.timeout = timeout; + return value.res; + } + const res = fn(...args); + cache.set(key, { timeout, res }); + console.log('Calculated: ', res); + return res; + }; +}; + +const sum = (a, b) => a + b; +const f1 = timerMemoize(sum, 10000); +f1(1, 2); +f1(1, 2); +f1(1, 2); +f1(2, 4); +f1(2, 4); +setTimeout(() => f1(2, 4), 9000); +setTimeout(() => f1(2, 4), 12000); +setTimeout(() => f1(2, 4), 22500); +setTimeout(() => f1(2, 4), 23000); \ No newline at end of file diff --git a/JavaScript/9-countMemoize.js b/JavaScript/9-countMemoize.js new file mode 100644 index 0000000..eab8876 --- /dev/null +++ b/JavaScript/9-countMemoize.js @@ -0,0 +1,49 @@ +'use strict'; + +const argKey = x => (x.toString() + ':' + typeof(x)); +const generateKey = arg => arg.map(argKey).join('|'); + +const countMemoize = (fn, max) => { + const cache = new Map(); + return (...args) => { + const key = generateKey(args); + if (cache.has(key)) { + const value = cache.get(key); + console.log('from cache:', value.res); + value.count += 1; + return value.res; + } + const res = fn(...args); + console.log('Calculated:', res); + if (cache.size > max) { + let [deleted, { count: num }] = cache.entries().next().value; + cache.forEach((value, keys) => { + const count = value.count; + if (num >= count) { + num = count; + deleted = keys; + } + }); + console.log('deleted: ', deleted); + cache.delete(deleted); + } + cache.set(key, { res, count: 1 }); + return res; + }; +}; + +const sum = (a, b) => a + b; +const f1 = countMemoize(sum, 3); +f1(1, 2); +f1(1, 2); +f1(1, 2); +f1(2, 4); +f1(2, 4); +f1(3, 4); +f1(4, 4); +f1(4, 4); +f1(3, 4); +f1(4, 4); +f1(4, 4); +f1(5, 4); +f1(5, 4); \ No newline at end of file diff --git a/JavaScript/a-sizeMemoize.js b/JavaScript/a-sizeMemoize.js new file mode 100644 index 0000000..12253e2 --- /dev/null +++ b/JavaScript/a-sizeMemoize.js @@ -0,0 +1,93 @@ +'use strict'; + +const argKey = x => (x.toString() + ':' + typeof(x)); +const generateKey = arg => arg.map(argKey).join('|'); + +const sizeMemoize = (fn, maxSize) => { + const cache = new Map(); + const sizeToBytes = (size) => { + if(/[TGMKBtgmkb]/.test(size)) { + const k = parseFloat(size.slice(0, size.length - 1)); + const char = size.slice(size.length - 1); + const tableOfSize = { + T: Math.pow(2, 40), + G: Math.pow(2, 30), + M: Math.pow(2, 20), + K: Math.pow(2, 10), + B: 1, + }; + return tableOfSize[char.toUpperCase()] * k; + } + else return parseFloat(size); + }; + const getSize = function(arg) { + if (!arg) return 0; + let countOfObj = 0; + const getSizeTable = { + number: 8, + boolean: 4, + string: arg.length * 2, + }; + if (typeof(arg) === 'object') { + for (const value of arg.values()) { + ({ res: arg } = value); + countOfObj += (getSizeTable[typeof(arg)] ? getSizeTable[typeof(arg)] : getSize(arg)); + } + return countOfObj; + } else { + const countOfArg = getSizeTable[typeof(arg)]; + return countOfArg; + } + }; + return (...args) => { + const key = generateKey(args); + if (cache.has(key)) { + const value = cache.get(key); + console.log('from cache:', value.res); + value.count += 1; + return value.res; + } + const res = fn(...args); + const inBytes = sizeToBytes(maxSize); + if (getSize(res) > inBytes) { + console.log('Size of result more than can hold cache!'); + console.log('Calculated:', res); + return res; + } + while (getSize(cache) + getSize(res) > inBytes) { + let [deleted, { count: num }] = cache.entries().next().value; + cache.forEach((value, key) => { + const count = value.count; + if (num >= count) { + num = count; + deleted = key; + } + }); + console.log('deleted:', deleted); + cache.delete(deleted); + } + console.log('Calculated:', res); + cache.set(key, { res, count: 1 }); + return res; + }; +}; +const sum = (a, b) => a + b; +const f1 = sizeMemoize(sum, '20'); +f1('s', 'qsssss'); +f1(1, 2); +f1(1, 2); +f1(true, false); +f1(2, 4); +f1(2, 4); +f1(2, 4); +f1(3, 4); +f1('22', 4); +f1('qqqqq', 'qqqqqqq'); +f1('qqqqq', 'qqqqq'); +f1(4, 4); +f1('q', 4); +f1(5, 4); +f1(5, 4); + + + diff --git a/JavaScript/b-syncAsyncMemoize.js b/JavaScript/b-syncAsyncMemoize.js new file mode 100644 index 0000000..ca68946 --- /dev/null +++ b/JavaScript/b-syncAsyncMemoize.js @@ -0,0 +1,53 @@ +'use strict'; + +const argKeySync = x => (x.toString() + ':' + typeof(x)); +const generateKeySync = arg => arg.map(argKeySync).join('|').concat('(Sync)'); +const generateKeyAsync = arg => arg.slice().shift().concat('(Async)'); +const fs = require('fs'); + +const syncAsyncMemoize = function(fn) { + const cache = new Map(); + return (...args) => { + if (typeof(args[args.length - 1]) === 'function') { + const callback = args.pop(); + const key = generateKeyAsync(args); + if (cache.has(key)) { + const value = cache.get(key); + console.log('Async cache'); + callback(value.err, value.data); + return; + } + fn(...args, (err, data) => { + console.log('Async calculated'); + cache.set(key, { err, data }); + callback(err, data); + }); + } else { + const key = generateKeySync(args); + if (cache.has(key)) { + const value = cache.get(key); + console.log('from cache:', value); + return value; + } + const res = fn(...args); + cache.set(key, res); + console.log('Calculated:', res); + return res; + } + }; +}; +const sum = (a, b) => a + b; +const f1 = syncAsyncMemoize(sum); +f1(1, 2); +f1(1, 2); +f1(2, 2); +f1(2, 2); +f1(2, 2); + +const readfile = syncAsyncMemoize(fs.readFile); +readfile('sizeMemoize.js', 'utf8', (err, data) => { + console.log(data.length); + readfile('sizeMemoize.js', 'utf8', (err, data) => { + console.log(data.length); + }); +}); diff --git a/JavaScript/c-memoizeUnity.js b/JavaScript/c-memoizeUnity.js new file mode 100644 index 0000000..197249b --- /dev/null +++ b/JavaScript/c-memoizeUnity.js @@ -0,0 +1,198 @@ +'use strict'; + +const fs = require('fs'); + +const argKeySync = x => (x.toString() + ':' + typeof(x)); +const generateKeySync = arg => arg.map(argKeySync).join('|').concat('(Sync)'); +const generateKeyAsync = arg => arg.slice().shift().concat('(Async)'); + +const sizeToBytes = (size) => { + if (/[TGMKBtgmkb]/.test(size)) { + const k = parseFloat(size.slice(0, size.length - 1)); + const char = size.slice(size.length - 1); + const tableOfSize = { + T: Math.pow(2, 40), + G: Math.pow(2, 30), + M: Math.pow(2, 20), + K: Math.pow(2, 10), + B: 1, + }; + return tableOfSize[char.toUpperCase()] * k; + } else return parseFloat(size); +}; +const getSize = function(arg) { + if (!arg) return 0; + let countOfObj = 0; + const getSizeTable = { + number: 8, + boolean: 4, + string: arg.length * 2, + }; + if (typeof(arg) === 'object') { + for (const value of arg.values()) { + ({ res: arg } = value); + countOfObj += (getSizeTable[typeof(arg)] ? + getSizeTable[typeof(arg)] : + getSize(arg)); + } + return countOfObj; + } else { + const countOfArg = getSizeTable[typeof(arg)]; + return countOfArg; + } +}; +const memoizeUnity = function(fn) { + let cache = new Map(); + const events = new Map(); + const memoized = (...args) => { + if (typeof(args[args.length - 1]) === 'function') { + const callback = args.pop(); + const key = generateKeyAsync(args); + if (cache.has(key)) { + const value = memoized.get(key); + callback(value.err, value.res); + return; + } + fn(...args, (err, res) => { + const value = memoized.add(key, { err, res }); + callback(value.err, value.res); + return; + }); + } else { + const key = generateKeySync(args); + if (cache.has(key)) { + return memoized.get(key); + } + const res = fn(...args); + memoized.add(key, { res }); + } + }; + + const methods = { + clear() { + console.log('Cache is cleared'); + if (events.has('clear')) memoized.emit('clear', cache); + cache = new Map(); + }, + add(key, res) { + const result = res.res; + if (events.has('add')) memoized.emit('add', res); + if (this.maxSize < getSize(result)) { + console.log('Size of result more than can hold cache!'); + console.log('Calculated:', result); + return result; + } + this.checkMaxSize(res.res); + this.checkMaxCount(); + if (this.time) { + res.timer = setTimeout(this.del, this.time, key); + } + console.log(`\x1b[32mNew value: ${res.res} is added to the cache`); + res.count = 1; + cache.set(key, res); + return res; + }, + del(key) { + const value = cache.get(key); + clearTimeout(value.timer); + if (events.has('del')) memoized.emit('del', value); + console.log(`\x1b[31mValue: ${value.res} is deleted from the cache`); + cache.delete(key); + }, + get(key) { + const value = cache.get(key); + console.log('\x1b[33mReturned value from cache:', value.res); + if (this.time) { + clearTimeout(value.timer); + value.timer = setTimeout(this.del, this.time, key); + } + value.count += 1; + return value; + }, + timeout(msec) { + this.time = msec; + if (this.time) { + cache.forEach((el, key) => { + console.log(el); + el.timer = setTimeout(this.del, msec, key); + }); + } + return this; + }, + setMaxCount(max) { + this.maxCount = max ? max : 0; + this.checkMaxCount(); + return this; + }, + checkMaxCount() { + if (this.maxCount) { + while (cache.size >= this.maxCount) { + this.countChecker(); + } + } + }, + setMaxSize(max) { + this.maxSize = sizeToBytes(max) ? sizeToBytes(max) : 0; + this.checkMaxSize(); + return this; + }, + checkMaxSize(res) { + if (this.maxSize) { + while (getSize(cache) + getSize(res) > this.maxSize) { + this.countChecker(); + } + } + }, + countChecker() { + let [deleted, { count: num }] = cache.entries().next().value; + cache.forEach((value, key) => { + const count = value.count; + if (num >= count) { + num = count; + deleted = key; + } + }); + this.del(deleted); + }, + on(name, callback) { + const event = events.get(name); + if (event) event.push(callback); + else events.set(name, [callback]); + }, + emit(name, ...data) { + const event = events.get(name); + if (event) event.forEach(fn => fn(...data)); + } + }; + Object.assign(memoized, methods); + return Object.assign(memoized, methods); +}; + + +const sum = (a, b) => a + b; +const f1 = memoizeUnity(sum); +f1.timeout(300).setMaxCount(3).setMaxSize('40B'); +f1(1, 1); +f1(1, 1); +setTimeout(() => f1(1, 1), 300); +f1(1, 1); +f1(1, 1); +f1(2, 1); +f1(2, 1); +f1(3, 1); +f1(3, 1); +f1(4, 1); +setTimeout(f1, 1488, '\x1b[41m\x1b[33m\x1b[3mNa ', 'Dooooooppppppppkkkyyyyyyy'); +f1.on('del', data => { + console.log(`Deleted: ${data.res}`); +}); + +const f2 = memoizeUnity(fs.readFile); +f2('./timerMemoize.js', 'utf8', (err, data) => { + if (err) console.log(err.message); + console.log('data length:', data.length); + f2('./timerMemoize.js', 'utf8', (err, data) => { + if (err) console.log(err.message); + console.log('data length:', data.length); + }); +}); 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