-
-
Notifications
You must be signed in to change notification settings - Fork 26
Homework tasks #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 2 commits
53e1958
56fefe5
7367d48
c4a9f22
d28df6d
d19d326
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
'use strict'; | ||
|
||
const memoize = (fn, msec = 100) => { | ||
let cache = {}; | ||
let timer = setTimeout(() => { | ||
console.log('Cache cleaned'); | ||
timer = null; | ||
cache = {}; | ||
}, msec); | ||
|
||
const setTimer = msec => { | ||
timer = setTimeout(() => { | ||
console.log('Cache cleaned'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Remove duplicate code |
||
timer = null; | ||
cache = {}; | ||
}, msec); | ||
}; | ||
|
||
const generateKey = (...args) => args.join('|'); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add types to cache key |
||
|
||
return (...args) => { | ||
if (!timer) setTimer(msec); | ||
const key = generateKey(...args); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Pass array to |
||
|
||
if (cache[key]) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Check type, aware of |
||
console.log(`From cache: ${args} = ${cache[key]}`); | ||
return cache[key]; | ||
} | ||
|
||
console.log(`Calculate: ${args} = ${fn(...args)}`); | ||
const res = fn(...args); | ||
cache[key] = res; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do not write undefined to cache |
||
console.log(cache); | ||
return res; | ||
}; | ||
}; | ||
|
||
const sum = (a, b) => a + b; | ||
|
||
const sumM = memoize(sum, 2000); | ||
|
||
//USAGE | ||
sumM(1, 2); | ||
sumM(1, 2); | ||
setTimeout(() => { | ||
sumM(1, 2); | ||
}, 2500); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
'use strict'; | ||
|
||
const memoizeLimited = (fn, size) => { | ||
const cache = {}; | ||
|
||
const generateKey = (...args) => args.join('|'); | ||
|
||
const leastUsed = () => { | ||
let toDelete = Object.keys(cache)[0]; | ||
for (const i in cache) { | ||
if (cache[i].uses < cache[toDelete].uses) { | ||
toDelete = i; | ||
} | ||
} | ||
console.log('Deleting', toDelete); | ||
return toDelete; | ||
}; | ||
|
||
return (...args) => { | ||
const key = generateKey(...args); | ||
|
||
if (cache[key]) { | ||
console.log(`From cache: ${args}`); | ||
cache[key].uses++; | ||
return cache[key].value; | ||
} | ||
|
||
if (Object.keys(cache).length === size) | ||
delete cache[leastUsed()]; | ||
|
||
const res = { value: fn(...args), uses: 0 }; | ||
console.log(`Calculating ${args}`); | ||
cache[key] = res; | ||
return cache[key].value; | ||
}; | ||
}; | ||
|
||
//USAGE | ||
|
||
const sum = (a, b) => a + b; | ||
const sumM = memoizeLimited(sum, 3); | ||
|
||
console.log(`sumM(1, 2) = ${sumM(1, 2)}`); //uses: 0 | ||
console.log(`sumM(2, 3) = ${sumM(2, 3)}`); //uses: 0 | ||
console.log(`sumM(1, 2) = ${sumM(1, 2)}`); //uses: 1 | ||
console.log(`sumM(2, 3) = ${sumM(2, 3)}`); //uses: 2 | ||
console.log(`sumM(1, 3) = ${sumM(1, 3)}`); //uses: 0 | ||
console.log(`sumM(5, 6) = ${sumM(5, 6)}`); //uses: 0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
'use strict'; | ||
|
||
const memoizeBytes = (fn, size) => { | ||
let cache = {}; | ||
|
||
const generateKey = (...args) => args.join('|'); | ||
|
||
const sizeToBytes = (size) => { | ||
const length = size.length; | ||
const data = parseFloat(size, 10); | ||
let k = 1; | ||
switch (size.charAt(length - 1)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
case 'T': k *= 1000; | ||
case 'G': k *= 1000; | ||
case 'M': k *= 1000; | ||
case 'K': k *= 1000; | ||
case 'B': break; | ||
default: break; | ||
} | ||
return data * k; | ||
}; | ||
|
||
const sizeInBytes = sizeToBytes(size); | ||
|
||
const getSize = (obj) => { | ||
let bytes = 0; | ||
for (const i in obj) { | ||
switch (typeof obj[i]) { | ||
case 'number': | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
bytes += 8; | ||
break; | ||
case 'boolean': | ||
bytes += 4; | ||
break; | ||
case 'string': | ||
bytes += obj[i].length * 2; | ||
break; | ||
case 'object': | ||
bytes += getSize(obj[i]); | ||
break; | ||
default: throw new Error('getSize: Wrong field type.'); | ||
} | ||
} | ||
return bytes; | ||
}; | ||
|
||
return (...args) => { | ||
const key = generateKey(...args); | ||
|
||
if (cache[key]) { | ||
console.log(`From cache: ${key}`); | ||
return cache[key]; | ||
} | ||
|
||
if (getSize(cache) >= sizeInBytes) { | ||
console.log(`Cache with size ${getSize(cache)} bytes cleaned`); | ||
cache = {}; | ||
} | ||
|
||
console.log(`Calculating: ${key}`); | ||
cache[key] = fn(...args); | ||
console.dir(`Cache size: ${getSize(cache)}`); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Calculate |
||
return fn(...args); | ||
}; | ||
}; | ||
|
||
//USAGE | ||
|
||
const sum = (a, b) => a + b; | ||
const sumB = memoizeBytes(sum, '32B'); | ||
console.log(`sumB(1, 2) = ${sumB(1, 2)}`); | ||
console.log(`sumB(1, 2) = ${sumB(1, 2)}`); | ||
console.log(`sumB(2, 3) = ${sumB(2, 3)}`); | ||
console.log(`sumB(3, 2) = ${sumB(3, 2)}`); | ||
console.log(`sumB(4, 2) = ${sumB(4, 2)}`); | ||
console.log(`sumB(2, 3) = ${sumB(2, 3)}`); | ||
console.log(`sumB(1, 3) = ${sumB(1, 3)}`); | ||
console.log(`sumB(4, 3) = ${sumB(4, 3)}`); | ||
console.log(`sumB(9, 3) = ${sumB(1, 3)}`); | ||
console.log(`sumB(8, 3) = ${sumB(8, 3)}`); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
'use strict'; | ||
|
||
const memeizeUniversal = fn => { | ||
const cache = {}; | ||
const generateKey = (...args) => args.join('|'); | ||
|
||
return (...args) => { | ||
let callback; | ||
if (typeof args[args.length - 1] === 'function') | ||
callback = args.pop(); | ||
const key = generateKey(...args); | ||
|
||
if (cache[key]) { | ||
if (callback) { | ||
console.log(`Async cache: ${key}`); | ||
callback(cache[key].err, cache[key].data); | ||
return; | ||
} | ||
console.log(`Sync cache: ${key}`); | ||
return cache[key]; | ||
} | ||
|
||
if (callback) { | ||
console.log(`Async calc: ${key}`); | ||
fn(...args, (err, data) => { | ||
cache[key] = { err, data }; | ||
callback(err, data); | ||
}); | ||
return; | ||
} | ||
console.log(`Sync calc: ${key}`); | ||
cache[key] = fn(...args); | ||
return cache[key]; | ||
}; | ||
}; | ||
|
||
//USAGE | ||
|
||
const fs = require('fs'); | ||
|
||
const asyncRead = memeizeUniversal(fs.readFile); | ||
|
||
asyncRead('b-universal.js', 'utf8', (err, data) => { | ||
console.log('data length:', data.length); | ||
asyncRead('b-universal.js', 'utf8', (err, data) => { | ||
console.log('data length:', data.length); | ||
}); | ||
}); | ||
|
||
const сум = (a, b) => a + ' => ' + b; | ||
const журба = memeizeUniversal(сум); | ||
console.log(журба('Грушевський', 'Житомир')); | ||
console.log(журба('Скоропадський', 'Мотовилівка')); | ||
console.log(журба('Грушевський', 'Житомир')); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
'use strict'; | ||
|
||
const generateKey = (...args) => args.join('|'); | ||
const getSize = (obj) => { | ||
let bytes = 0; | ||
for (const i in obj) { | ||
switch (typeof obj[i]) { | ||
case 'number': | ||
bytes += 8; | ||
break; | ||
case 'boolean': | ||
bytes += 4; | ||
break; | ||
case 'string': | ||
bytes += obj[i].length * 2; | ||
break; | ||
case 'object': | ||
bytes += getSize(obj[i]); | ||
break; | ||
default: throw new Error('getSize: Wrong field type.'); | ||
} | ||
} | ||
return bytes; | ||
}; | ||
|
||
const memoizator = fn => { | ||
let cache = {}; | ||
const events = []; | ||
|
||
const func = (...args) => { | ||
const key = generateKey(...args); | ||
|
||
if (func.timeout && !func.timer) { | ||
func.timer = setTimeout(() => { | ||
cache = {}; | ||
console.log(`Cache cleared after ${func.timeout} msec`); | ||
}, func.timeout); | ||
} | ||
|
||
if (cache[key]) { | ||
console.log(`From cache ${key}`); | ||
return cache[key]; | ||
} | ||
|
||
if (func.maxSize && getSize(cache) >= func.maxSize) { | ||
console.log(`Cache with size ${getSize(cache)} bytes cleaned`); | ||
cache = {}; | ||
} | ||
|
||
const cacheSize = Object.keys(cache).length; | ||
if (func.maxCount && cacheSize >= func.maxCount) { | ||
console.log(`Cache with length ${cacheSize} cleaned`); | ||
} | ||
|
||
console.log(`Calc ${key}`); | ||
cache[key] = fn(...args); | ||
return cache[key]; | ||
}; | ||
|
||
func.clear = () => { | ||
console.log('Cache cleared'); | ||
cache = {}; | ||
}; | ||
|
||
func.add = (key, value) => { | ||
if (cache[key]) throw new Error('This key already exists'); | ||
else cache[key] = value; | ||
console.log(`${key} added`); | ||
}; | ||
|
||
func.get = (key) => cache[key]; | ||
|
||
func.del = (key) => { | ||
if (cache[key]) { | ||
console.log(`${key} deleted`); | ||
delete cache[key]; | ||
return; | ||
} | ||
console.log(`There is no ${key}`); | ||
}; | ||
|
||
func.on = (name, fn) => { | ||
if (events[name]) throw new Error('Event already exists'); | ||
if (!['clear', 'add', 'del'].find((el) => (el === name))) | ||
throw new Error('Wrong event name'); | ||
events[name] = fn; | ||
}; | ||
|
||
func.emit = (name, data) => { | ||
if (name === 'clear') { | ||
events[name](cache); | ||
func.clear(); | ||
return true; | ||
} | ||
if (name === 'add') { | ||
const res = data.map((el) => events[name](el)); | ||
res.map((el, key) => func.add(key, el)); | ||
return true; | ||
} | ||
if (name === 'del') { | ||
const res = []; | ||
res.push(events[name](...data, cache)); | ||
res.map((key) => func.del(key)); | ||
return true; | ||
} | ||
throw new Error('Frong event name'); | ||
}; | ||
|
||
func.timeout = null; | ||
func.maxSize = null; | ||
func.maxCount = null; | ||
|
||
return func; | ||
}; | ||
|
||
//USAGE | ||
|
||
const sum = (a, b) => a + b; | ||
const sumM = memoizator(sum); | ||
console.log(sumM(1, 1)); | ||
sumM.maxCount = 3; | ||
sumM.timeout = 100; | ||
sumM.maxSize = 32; | ||
|
||
sumM.on('clear', (cache) => console.dir({ cache })); | ||
sumM.emit('clear'); | ||
|
||
const fibbo = (n) => (n < 2 ? 1 : fibbo(n - 1) + fibbo(n - 2)); | ||
sumM.on('add', fibbo); | ||
sumM.emit('add', [1, 2, 3]); | ||
|
||
sumM(1, 2); | ||
sumM.on('del', (el) => generateKey(el, el + 1)); | ||
sumM.emit('del', [1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
8-timeout.js