Created
March 12, 2020 07:47
-
-
Save mantaskaveckas/a61f46e2dceb5facfa5b0fe456039225 to your computer and use it in GitHub Desktop.
Sandbox
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
* Strings | |
* | |
* .split() | |
* .toLowercase() | |
* .substring() | |
* .startsWidth() | |
*/ | |
// Reverse a string | |
// console.log(reverse('Foo')); // 'ooF' | |
function reverse(str) { | |
return str | |
.split("") | |
.reverse() | |
.join(""); | |
} | |
// Remove duplicates from a string | |
// console.log(removeDuplicates('This is is a test test string')); // 'This is a test string' | |
function removeDuplicates(str) { | |
const set = new Set(str.split(" ")); | |
return [...set].join(" "); | |
} | |
/** | |
* | |
* Arrays | |
* | |
* Object.entries() | |
* Array.from() | |
* [...items] | |
* | |
* .isArray() | |
* .filter() | |
* .reduce() | |
* .concat() | |
* .join() | |
* .shift() | |
* .unshift() | |
* .pop() | |
* .push() | |
* .map() | |
*/ | |
// Create a fn to flatten an array | |
// console.log(flatten([1, 2, [3, 4, [5, 6]], 7])); // [1, 2, 3, 4, 5, 6, 7] | |
function flatten(arr) { | |
return arr.reduce((acc, item) => { | |
return acc.concat(Array.isArray(item) ? flatten(item) : item); | |
}, []); | |
} | |
/** | |
* | |
* Scope | |
* | |
* .call() | |
* .apply() | |
* .bind() | |
*/ | |
// Implement Function.prototype.bind() | |
// const foo = function() { | |
// console.log(this.bar); | |
// } | |
// let baz = foo.bind({ bar: 'hi' }); | |
// baz(); // 'Hi' | |
Function.prototype.bind = function(context) { | |
const fn = this; | |
return function() { | |
fn.call(context); | |
}; | |
}; | |
/** | |
* | |
* Timing | |
* | |
* setInterval() | |
* setTimeout() | |
*/ | |
// Implement debounce | |
// const debouncedFn = debounce(function() { console.log('A')}, 100); | |
// debouncedFn(); | |
function debounce(fn, time) { | |
let setTimeoutId; | |
return function() { | |
if (setTimeoutId) { | |
clearTimeout(setTimeoutId); | |
} | |
setTimeoutId = setTimeout(() => { | |
fn.apply(this, arguments); | |
setTimeoutId = null; | |
}, time); | |
}; | |
} | |
/** | |
* | |
* Trees | |
*/ | |
// We have two identical DOM trees, A and B. For DOM tree A, we have | |
// the location of the element. Create a function to find that same element | |
// in tree B. | |
function reversePath(element, root) { | |
const path = []; | |
let pointer = element; | |
while (pointer.parent) { | |
const index = pointer.parent.children.indexOf(pointer); | |
path.push(index); | |
pointer = pointer.parent; | |
} | |
pointer = root; | |
while (path.length) { | |
pointer = pointer.children[path.pop()]; | |
} | |
} | |
/** | |
* | |
* Rendering | |
* | |
* requestAnimationFrame() | |
*/ | |
// Create a function to move an element. The function arguments are, | |
// distance, duration, and the element to move. | |
function moveElement(duration, distance, element) { | |
const start = performance.now(); | |
function move(currentTime) { | |
const elapsed = currentTime - start; | |
const progress = elapsed / duration; | |
const amountToMove = progress * distance; | |
element.style.transform = `translateX(${amountToMove}px)`; | |
if (amountToMove < distance) { | |
requestAnimationFrame(move); | |
} | |
} | |
requestAnimationFrame(move); | |
} | |
/** | |
* | |
* Promises | |
*/ | |
// Implement `sleep` function | |
// async function run() { | |
// await sleep(500); | |
// console.log("hello"); | |
// await sleep(500); | |
// console.log("world"); | |
// } | |
// run(); | |
function sleep(time) { | |
return new Promise(resolve => { | |
const timeoutId = setTimeout(() => { | |
clearTimeout(timeoutId); | |
resolve(); | |
}, time); | |
}); | |
} | |
// Promisify a function | |
function promisify(fn) { | |
return function(...args) { | |
return new Promise(function(resolve, reject) { | |
function cb(result) { | |
resolve(result); | |
} | |
fn.apply(this, args.concat(cb)); | |
}); | |
}; | |
} | |
/** | |
* | |
* Recursion | |
*/ | |
// Fibonacci | |
function fibonacci(num) { | |
if (num <= 2) { | |
return 1; | |
} else { | |
return fibonacci(num - 1) + fibonacci(num - 2); | |
} | |
} | |
// Factorial | |
function factorial(num) { | |
if (num < 2) { | |
return 1; | |
} | |
return num * factorial(num - 1); | |
} | |
/** | |
* | |
* Bubble Sort | |
* O(n2) | |
*/ | |
function bubbleSort(nums) { | |
do { | |
let swapped = false; | |
for (let i = 0; i < nums.length; i++) { | |
if (nums[i] > nums[i + 1]) { | |
let temp = nums[i]; | |
nums[i] = nums[i + 1]; | |
nums[i + 1] = temp; | |
swapped = true; | |
} | |
} | |
} while (swapped); | |
} | |
/** | |
* | |
* Insertion Sort | |
* O(n) - O(n2) | |
*/ | |
function insertionSort(nums) { | |
for (let i = 1; i < nums.length; i++) { | |
for (let j = 0; j < i; j++) { | |
if (nums[i] < nums[j]) { | |
let spliced = nums.splice(i, 1); | |
nums.splice(j, 0, spliced[0]); | |
} | |
} | |
} | |
} | |
/** | |
* | |
* Merge Sort | |
* O(n log n) | |
*/ | |
function mergeSort(nums) { | |
if (nums.length < 2) { | |
return nums; | |
} | |
const length = nums.length; | |
const middle = Math.floor(length / 2); | |
const left = nums.slice(0, middle); | |
const right = nums.slice(middle); | |
return merge(mergeSort(left), mergeSort(right)); | |
} | |
function merge(left, right) { | |
const results = []; | |
while (left.length && right.length) { | |
if (left[0] <= right[0]) { | |
results.push(left.shift()); | |
} else { | |
results.push(right.shift()); | |
} | |
} | |
return results.concat(left, right); | |
} | |
/** | |
* | |
* Quick Sort | |
* O(n log n) | |
*/ | |
function quickSort(nums) { | |
if (nums.length <= 1) { | |
return nums; | |
} | |
const pivot = nums[length - 1]; | |
const left = []; | |
const right = []; | |
for (let i = 0; i < nums.length - 1; i++) { | |
if (nums[i] < pivot) { | |
left.push(nums[i]); | |
} else { | |
right.push(nums[i]); | |
} | |
} | |
return [...quickSort(left), pivot, ...quickSort(right)]; | |
} | |
/** | |
* | |
* Array List | |
* Adds & Deletes - O(1) | |
* Gets - O(n) | |
*/ | |
class ArrayList { | |
constructor() { | |
this.length = 0; | |
this.data = {}; | |
} | |
push(value) { | |
this.data[this.length] = value; | |
this.length++; | |
} | |
pop() { | |
const ans = this.data[this.length - 1]; | |
delete this.data[this.length - 1]; | |
this.length--; | |
return ans; | |
} | |
get(index) { | |
return this.data[index]; | |
} | |
delete(index) { | |
const ans = this.data[index]; | |
this._collapseTo(index); | |
return ans; | |
} | |
_collapseTo(index) { | |
for (let i = index; i < this.length; i++) { | |
this.data[i] = this.data[i + 1]; | |
} | |
delete this.data[this.length - 1]; | |
this.length--; | |
} | |
serialize() { | |
return this.data; | |
} | |
} | |
/** | |
* | |
* Linked List | |
* Adds & Deletes - O(1) | |
* Gets - O(n) | |
*/ | |
class LinkedList { | |
constructor() { | |
this.tail = this.head = null; | |
this.length = 0; | |
} | |
push(value) { | |
const node = new Node(value); | |
this.length++; | |
if (!this.head) { | |
this.head = node; | |
} else { | |
this.tail.next = node; | |
} | |
this.tail = node; | |
} | |
pop() { | |
if (!this.head) return null; | |
if (this.head === this.tail) { | |
const node = this.head; | |
this.head = this.tail = null; | |
return node.value; | |
} | |
const penultimate = this._find( | |
null, | |
(value, nodeValue, i, current) => current.next === this.tail | |
); | |
const ans = penultimate.next.value; | |
penultimate.next = null; | |
this.tail = penultimate; | |
this.length--; | |
return ans; | |
} | |
_find(value, test = this.test) { | |
let current = this.head; | |
let i = 0; | |
while (current) { | |
if (test(value, current.value, i, current)) { | |
return current; | |
} | |
current = current.next; | |
i++; | |
} | |
return null; | |
} | |
get(index) { | |
const node = this._find(index, this.testIndex); | |
if (!node) return null; | |
return node.value; | |
} | |
delete(index) { | |
if (index === 0) { | |
const head = this.head; | |
if (head) { | |
this.head = head.next; | |
} else { | |
this.head = null; | |
} | |
this.length--; | |
return head.value; | |
} | |
const node = this._find(index - 1, this.testIndex); | |
const excise = node.next; | |
if (!excise) return null; | |
node.next = excise.next; | |
if (!node.next.next) this.tail = node.next; | |
this.length--; | |
return excise.value; | |
} | |
test(search, nodeValue) { | |
return search === nodeValue; | |
} | |
testIndex(search, __, i) { | |
return search === i; | |
} | |
serialize() { | |
const ans = []; | |
let current = this.head; | |
if (!current) return ans; | |
while (current) { | |
ans.push(current.value); | |
current = current.next; | |
} | |
return ans; | |
} | |
} | |
class Node { | |
constructor(value) { | |
this.value = value; | |
this.next = null; | |
} | |
} | |
/** | |
* | |
* Binary Search Tree | |
* O(log n) | |
*/ | |
class Tree { | |
constructor() { | |
this.root = null; | |
} | |
add(value) { | |
if (this.root === null) { | |
this.root = new BSTNode(value); | |
} else { | |
let current = this.root; | |
while (true) { | |
if (current.value > value) { | |
// go left | |
if (current.left) { | |
current = current.left; | |
} else { | |
current.left = new BSTNode(value); | |
break; | |
} | |
} else { | |
// go right | |
if (current.right) { | |
current = current.right; | |
} else { | |
current.right = new BSTNode(value); | |
break; | |
} | |
} | |
} | |
} | |
return this; | |
} | |
toJSON() { | |
return JSON.stringify(this.root.serialize(), null, 4); | |
} | |
toObject() { | |
return this.root.serialize(); | |
} | |
} | |
class BSTNode { | |
constructor(value = null, left = null, right = null) { | |
this.left = left; | |
this.right = right; | |
this.value = value; | |
} | |
serialize() { | |
const ans = { value: this.value }; | |
ans.left = this.left === null ? null : this.left.serialize(); | |
ans.right = this.right === null ? null : this.right.serialize(); | |
return ans; | |
} | |
} | |
/** | |
* | |
* Hash Table | |
* O(1) | |
*/ | |
class HashTableSet { | |
constructor() { | |
this.table = new Array(255); | |
} | |
add(input) { | |
this.table[this.hash(input, 255)] = input; | |
} | |
check(input) { | |
return !!this.table[this.hash(input, 255)]; | |
} | |
hash(input, max) { | |
let num = 0; | |
for (let i = 0; i < input.length; i++) { | |
num += input.charCodeAt(i) * i; | |
} | |
return num % max; | |
} | |
} | |
/** | |
* | |
* Test Runner | |
*/ | |
const describe = (description, callback) => { | |
console.log(description); | |
callback(); | |
}; | |
const it = (message, callback) => describe(` ${message}`, callback); | |
const matchers = expression => ({ | |
toBe: assertion => { | |
if (expression === assertion) { | |
console.log("PASS"); | |
return true; | |
} else { | |
console.log("FAIL"); | |
return false; | |
} | |
} | |
}); | |
const expect = expression => matchers(expression); | |
function multiplier(a, b) { | |
return a * b; | |
} | |
describe("multiplier", () => { | |
it("multiplies two numbers", () => { | |
const result = multiplier(5, 2); | |
expect(result).toBe(10); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment