Skip to content

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

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions JavaScript/8-timeout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict';

const memoize = (fn, msec = 100) => {
const cache = {};
let timer = null;
const hasKey = (key) => Object.keys(cache).includes(key);
const generateKey = (args) => {
let key = '';
for (const arg of args)
key += `${arg}~${typeof arg}|`;
return key;
};

const throwGarbage = () => {
const cleaningTime = new Date();
const removingTime = cleaningTime - msec;

const toDelete = Object.keys(cache)
.filter(key => cache[key].lastUse >= removingTime);

for (const key in cache) {
if (toDelete.includes(key)) {
console.log(`${key} deleted.`);
delete cache[key];
}
if (Object.keys(cache).length === 0) {
console.log('Cache is empty');
clearInterval(timer);
timer = null;
}
}
};

const setTimer = (msec) => {
const timer = setInterval(() => throwGarbage(), msec);
return timer;
};

timer = setTimer(msec);

const func = (...args) => {
if (!timer) timer = setTimer(msec);
const key = generateKey(args);

if (hasKey(key)) {
console.log(`From cache: ${args} = ${cache[key].value}`);
cache[key].lastUse = new Date();
console.log(cache);
return cache[key].value;
}

console.log(`Calculate: ${args} = ${fn(...args)}`);
const res = fn(...args);
if (res !== undefined)
cache[key] = { value: res, lastUse: new Date() };
console.log(cache);
return res;
};

return func;
};

const sum = (a, b) => a + b;

const sumM = memoize(sum, 250);

//USAGE
sumM(1, -1);
sumM(2, -1);
setTimeout(() => {
sumM(1, -1);
setTimeout(() => sumM(2, -1), 100);
setTimeout(() => {
sumM(2, 3);
setTimeout(() => sumM(3, 4), 1000);
}, 500);
}, 200);
48 changes: 48 additions & 0 deletions JavaScript/9-least.js
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
76 changes: 76 additions & 0 deletions JavaScript/a-bytes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
'use strict';

const memoizeBytes = (fn, size = '1K', logging = true) => {
let cache = new Map();

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)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use new Map or {} for large cases

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;
const dictTypes = {
number: () => 8,
boolean: () => 4,
string: (str) => str.length * 2,
object: (ob) => getSize(ob),
};
obj.forEach((value) => {
const getBytes = dictTypes[typeof value];
bytes += getBytes(value);
});
return bytes;
};

return (...args) => {
const key = generateKey(...args);
const record = cache.get(key);

if (record) {
if (logging) console.log(`From cache: ${key}`);
return cache[key];
}

const sizeOfCache = getSize(cache);
if (sizeOfCache >= sizeInBytes) {
console.log(`Cache with size ${sizeOfCache} bytes cleaned`);
cache = new Map();
}

if (logging) console.log(`Calculating: ${key}`);
const res = fn(...args);
cache.set(key, res);
if (logging) console.dir(`Cache size: ${sizeOfCache}`);
return res;
};
};

//USAGE

const sum = (a, b) => a + b;
const sum1 = memoizeBytes(sum, '32B');
console.log(`sum1(1, 2) = ${sum1(1, 2)}`);
console.log(`sum1(1, 2) = ${sum1(1, 2)}`);
console.log(`sum1(2, 3) = ${sum1(2, 3)}`);
console.log(`sum1(3, 2) = ${sum1(3, 2)}`);
console.log(`sum1(4, 2) = ${sum1(4, 2)}`);
console.log(`sum1(2, 3) = ${sum1(2, 3)}`);
console.log(`sum1(1, 3) = ${sum1(1, 3)}`);

const sum2 = memoizeBytes(sum, '0.5K', false);
for (let i = 0; i < 100; i++, sum2(i, i - 1));
54 changes: 54 additions & 0 deletions JavaScript/b-universal.js
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(журба('Грушевський', 'Житомир'));
134 changes: 134 additions & 0 deletions JavaScript/c-object.js
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]);
Loading