UNPKG

ds-algo-study

Version:

Just experimenting with publishing a package

205 lines (166 loc) 6.98 kB
const chai = require('chai'); const names = Array.from(require('./names').keys()); const solution = require('../problems/friends-of'); const { expect } = chai; const { friendsOf } = solution; function randomInteger(min, max) { return Math.floor(Math.random() * (max - min)) + min; } function randomName() { return names[randomInteger(0, names.length)]; } function randomFriends(without) { const friends = new Set(); const listSize = randomInteger(1, 6); for (let i = 0; i < listSize; i += 1) { friends.add(randomName()); } friends.delete(without); return Array.from(friends); } function cloneList(list) { return JSON.parse(JSON.stringify(list)); } function buildFriendsList(seed, distance, list) { const friendsLists = []; friendsLists[0] = seed; for (let i = 1; i < distance; i += 1) { const previous = friendsLists[i - 1]; friendsLists[i] = []; for (let name of previous) { friendsLists[i] = Array.from(new Set(friendsLists[i].concat(list[name]))); } } return friendsLists; } /* Above function obfuscated into following code below using obfuscator.io. */ // const _0x35c1=['from','concat'];(function(_0x14133d,_0x35c145){const _0x33f76e=function(_0x8eaf13){while(--_0x8eaf13){_0x14133d['push'](_0x14133d['shift']());}};_0x33f76e(++_0x35c145);}(_0x35c1,0xb8));const _0x33f7=function(_0x14133d,_0x35c145){_0x14133d=_0x14133d-0x0;let _0x33f76e=_0x35c1[_0x14133d];return _0x33f76e;};function buildFriendsList(_0x2ed3fc,_0x5d7a0c,_0x33182e){const _0x30d82b=[];_0x30d82b[0x0]=_0x2ed3fc;for(let _0x47a018=0x1;_0x47a018<_0x5d7a0c;_0x47a018+=0x1){const _0x3f9a4c=_0x30d82b[_0x47a018-0x1];_0x30d82b[_0x47a018]=[];for(let _0x55707d of _0x3f9a4c){_0x30d82b[_0x47a018]=Array[_0x33f7('0x0')](new Set(_0x30d82b[_0x47a018][_0x33f7('0x1')](_0x33182e[_0x55707d])));}}return _0x30d82b;} describe('friendsOf()', () => { context('when called with an empty adjacency list', () => { it('returns undefined', () => { const name = randomName(); const distance = randomInteger(1, names.length); const list = {}; const result = friendsOf(list, name, distance); expect(result).to.be.undefined; }); }); context('when called with a name that does not exist in the adjacency list', () => { it('returns undefined', () => { const name = Math.random().toString(); const distance = randomInteger(1, names.length); const list = {[names[0]]: []}; const result = friendsOf(list, name, distance); expect(result).to.be.undefined; }); }); context('when called with a name that exists in the dependency list', () => { for (let distance = 1; distance <= names.length; distance += 20) { it (`returns an empty list for distances ${distance} - ${distance + 19} for someone with no friends`, () => { const list = names.reduce((acc, name, i) => { acc[name] = [names[(i + 1) % names.length]]; return acc; }, {}); const friendless = randomName(); list[friendless] = []; for (let d = distance; d <= distance + 20; d += 1) { const result = friendsOf(cloneList(list), friendless, distance); expect(result).to.eql([]); } }); } it ('returns an empty list for someone only friends with them self for an arbitrarily large distance', function () { const list = names.reduce((acc, name, i) => { acc[name] = [names[(i + 1) % names.length]]; return acc; }, {}); const target = randomName(); list[target] = [target]; const result = friendsOf(cloneList(list), target, names.length + 1); expect(result).to.eql([]); }); it ('returns a single name if Person A is friends with only Person B and Person B is friends with only Person A', function () { const list = names.reduce((acc, name, i) => { acc[name] = [names[(i + 1) % names.length]]; return acc; }, {}); const target1 = randomName(); let target2 = randomName(); while (target1 === target2) { target2 = randomName(); } list[target1] = [target2]; list[target2] = [target1]; const result = friendsOf(cloneList(list), target1, 10); expect(result).to.eql([target2]); }); it ('returns the persons immediate list of friends for distance 1', () => { const list = names.reduce((acc, name) => { acc[name] = randomFriends(name); return acc; }, {}); const target = randomName(); const expected = list[target].filter(x => x !== target); const result = friendsOf(cloneList(list), target, 1); expect(result).to.eql(expected); }); it ('returns the persons friends and friends of friends for distance 2', () => { const target = randomName(); const friendsList = new Set(randomFriends(target)); const secondList = new Set(); const list = names.reduce((acc, name) => { if (name === target) { acc[name] = Array.from(friendsList); } else { acc[name] = randomFriends(name); if (friendsList.has(name)) { for (let n of acc[name]) { secondList.add(n); } if (!acc[name].includes(target)) { acc[name].push(target); } } } return acc; }, {}); friendsList.delete(target); secondList.delete(target); const expected = Array.from(new Set(Array.from(friendsList).concat(Array.from(secondList)))); expected.sort(); const result = friendsOf(cloneList(list), target, 2); result.sort(); expect(result).to.eql(expected); }); it ('returns all reachable people for an arbitrarily large distance', function () { this.timeout(10000); const target = randomName(); const distance = randomInteger(10, 15); const list = names.reduce((acc, name) => { acc[name] = randomFriends(name); return acc; }, {}); const friendsLists = buildFriendsList(list[target], distance, list); const expectedSet = new Set(Array.prototype.concat.apply([], friendsLists)); expectedSet.delete(target); const expected = Array.from(expectedSet); expected.sort(); const result = friendsOf(cloneList(list), target, distance); result.sort(); expect(result).to.eql(expected); }); it ('returns all people for a fully-connected graph for a number larger than the number of people in the graph', function () { this.timeout(10000); const list = names.reduce((acc, name, i) => { acc[name] = [names[(i + 1) % names.length]]; return acc; }, {}); const target = randomName(); const expected = names.filter(x => x !== target); expected.sort() const result = friendsOf(cloneList(list), target, names.length + 1); result.sort(); expect(result).to.eql(expected); }); }); });