├── .gitignore ├── LICENSE ├── README.md ├── completed_exercises ├── anagrams │ ├── index.js │ └── test.js ├── bst │ ├── index.js │ └── test.js ├── capitalize │ ├── index.js │ └── test.js ├── chunk │ ├── index.js │ └── test.js ├── circular │ ├── index.js │ ├── linkedlist.js │ └── test.js ├── events │ ├── example.html │ ├── index.js │ └── test.js ├── fib │ ├── index.js │ └── test.js ├── fizzbuzz │ ├── index.js │ └── test.js ├── fromlast │ ├── index.js │ ├── linkedlist.js │ └── test.js ├── levelwidth │ ├── index.js │ ├── node.js │ └── test.js ├── linkedlist │ ├── directions.html │ ├── index.js │ └── test.js ├── matrix │ ├── index.js │ └── test.js ├── maxchar │ ├── index.js │ └── test.js ├── midpoint │ ├── index.js │ ├── linkedlist.js │ └── test.js ├── package.json ├── palindrome │ ├── index.js │ └── test.js ├── pyramid │ ├── index.js │ └── test.js ├── qfroms │ ├── index.js │ ├── stack.js │ └── test.js ├── queue │ ├── index.js │ └── test.js ├── reverseint │ ├── index.js │ └── test.js ├── reversestring │ ├── index.js │ └── test.js ├── sorting │ ├── index.js │ └── test.js ├── stack │ ├── index.js │ └── test.js ├── steps │ ├── index.js │ └── test.js ├── tree │ ├── index.js │ └── test.js ├── validate │ ├── index.js │ ├── node.js │ └── test.js ├── vowels │ ├── index.js │ └── test.js └── weave │ ├── index.js │ ├── queue.js │ └── test.js ├── diagrams ├── 10 │ ├── .gitkeep │ └── diagrams.xml ├── 01 │ ├── .gitkeep │ └── diagrams.xml ├── 02 │ ├── .gitkeep │ └── diagrams.xml ├── 03 │ ├── .gitkeep │ └── diagrams.xml ├── 04 │ ├── .gitkeep │ └── diagrams.xml ├── 05 │ ├── .gitkeep │ └── diagrams.xml ├── 06 │ ├── .gitkeep │ └── diagrams.xml ├── 07 │ ├── .gitkeep │ └── diagrams.xml ├── 08 │ ├── .gitkeep │ └── diagrams.xml └── 09 │ ├── .gitkeep │ └── diagrams.xml └── exercises ├── anagrams ├── index.js └── test.js ├── bst ├── index.js └── test.js ├── capitalize ├── index.js └── test.js ├── chunk ├── index.js └── test.js ├── circular ├── index.js ├── linkedlist.js └── test.js ├── events ├── example.html ├── index.js └── test.js ├── fib ├── index.js └── test.js ├── fizzbuzz ├── index.js └── test.js ├── fromlast ├── index.js ├── linkedlist.js └── test.js ├── levelwidth ├── index.js ├── node.js └── test.js ├── linkedlist ├── directions.html ├── index.js └── test.js ├── matrix ├── index.js └── test.js ├── maxchar ├── index.js └── test.js ├── midpoint ├── index.js ├── linkedlist.js └── test.js ├── package.json ├── palindrome ├── index.js └── test.js ├── pyramid ├── index.js └── test.js ├── qfroms ├── index.js ├── stack.js └── test.js ├── queue ├── index.js └── test.js ├── reverseint ├── index.js └── test.js ├── reversestring ├── index.js └── test.js ├── sorting ├── index.js └── test.js ├── stack ├── index.js └── test.js ├── steps ├── index.js └── test.js ├── tree ├── index.js └── test.js ├── validate ├── index.js ├── node.js └── test.js ├── vowels ├── index.js └── test.js └── weave ├── index.js ├── queue.js └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AlgoCasts 2 | 3 | Companion repo to [The Coding Inteview Bootcamp: Algorithms + Data Structures](https://www.udemy.com/course/coding-interview-bootcamp-algorithms-and-data-structure/) 4 | -------------------------------------------------------------------------------- /completed_exercises/anagrams/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Check to see if two provided strings are anagrams of eachother. 3 | // One string is an anagram of another if it uses the same characters 4 | // in the same quantity. Only consider characters, not spaces 5 | // or punctuation. Consider capital letters to be the same as lower case 6 | // --- Examples 7 | // anagrams('rail safety', 'fairy tales') --> True 8 | // anagrams('RAIL! SAFETY!', 'fairy tales') --> True 9 | // anagrams('Hi there', 'Bye there') --> False 10 | 11 | function anagrams(stringA, stringB) { 12 | return cleanString(stringA) === cleanString(stringB); 13 | } 14 | 15 | function cleanString(str) { 16 | return str 17 | .replace(/[^\w]/g, '') 18 | .toLowerCase() 19 | .split('') 20 | .sort() 21 | .join(''); 22 | } 23 | 24 | module.exports = anagrams; 25 | 26 | // function anagrams(stringA, stringB) { 27 | // const aCharMap = buildCharMap(stringA); 28 | // const bCharMap = buildCharMap(stringB); 29 | // 30 | // if (Object.keys(aCharMap).length !== Object.keys(bCharMap).length) { 31 | // return false; 32 | // } 33 | // 34 | // for (let char in aCharMap) { 35 | // if (aCharMap[char] !== bCharMap[char]) { 36 | // return false; 37 | // } 38 | // } 39 | // 40 | // return true; 41 | // } 42 | // 43 | // function buildCharMap(str) { 44 | // const charMap = {}; 45 | // 46 | // for (let char of str.replace(/[^\w]/g, '').toLowerCase()) { 47 | // charMap[char] = charMap[char] + 1 || 1; 48 | // } 49 | // 50 | // return charMap; 51 | // } 52 | -------------------------------------------------------------------------------- /completed_exercises/anagrams/test.js: -------------------------------------------------------------------------------- 1 | const anagrams = require('./index.js'); 2 | 3 | test('anagrams function exists', () => { 4 | expect(typeof anagrams).toEqual('function'); 5 | }); 6 | 7 | test('"hello" is an anagram of "llohe"', () => { 8 | expect(anagrams('hello', 'llohe')).toBeTruthy(); 9 | }); 10 | 11 | test('"Whoa! Hi!" is an anagram of "Hi! Whoa!"', () => { 12 | expect(anagrams('Whoa! Hi!', 'Hi! Whoa!')).toBeTruthy(); 13 | }); 14 | 15 | test('"One One" is not an anagram of "Two two two"', () => { 16 | expect(anagrams('One One', 'Two two two')).toBeFalsy(); 17 | }); 18 | 19 | test('"One one" is not an anagram of "One one c"', () => { 20 | expect(anagrams('One one', 'One one c')).toBeFalsy(); 21 | }); 22 | 23 | test('"A tree, a life, a bench" is not an anagram of "A tree, a fence, a yard"', () => { 24 | expect( 25 | anagrams('A tree, a life, a bench', 'A tree, a fence, a yard') 26 | ).toBeFalsy(); 27 | }); 28 | -------------------------------------------------------------------------------- /completed_exercises/bst/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Implement the Node class to create 3 | // a binary search tree. The constructor 4 | // should initialize values 'data', 'left', 5 | // and 'right'. 6 | // 2) Implement the 'insert' method for the 7 | // Node class. Insert should accept an argument 8 | // 'data', then create an insert a new node 9 | // at the appropriate location in the tree. 10 | // 3) Implement the 'contains' method for the Node 11 | // class. Contains should accept a 'data' argument 12 | // and return the Node in the tree with the same value. 13 | // If the value isn't in the tree return null. 14 | 15 | class Node { 16 | constructor(data) { 17 | this.data = data; 18 | this.left = null; 19 | this.right = null; 20 | } 21 | 22 | insert(data) { 23 | if (data < this.data && this.left) { 24 | this.left.insert(data); 25 | } else if (data < this.data) { 26 | this.left = new Node(data); 27 | } else if (data > this.data && this.right) { 28 | this.right.insert(data); 29 | } else if (data > this.data) { 30 | this.right = new Node(data); 31 | } 32 | } 33 | 34 | contains(data) { 35 | if (this.data === data) { 36 | return this; 37 | } 38 | 39 | if (this.data < data && this.right) { 40 | return this.right.contains(data); 41 | } else if (this.data > data && this.left) { 42 | return this.left.contains(data); 43 | } 44 | 45 | return null; 46 | } 47 | } 48 | 49 | module.exports = Node; 50 | -------------------------------------------------------------------------------- /completed_exercises/bst/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./index'); 2 | 3 | test('Node is a constructor', () => { 4 | expect(typeof Node.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('Node can insert correctly', () => { 8 | const node = new Node(10); 9 | node.insert(5); 10 | node.insert(15); 11 | node.insert(17); 12 | 13 | expect(node.left.data).toEqual(5); 14 | expect(node.right.data).toEqual(15); 15 | expect(node.right.right.data).toEqual(17); 16 | }); 17 | 18 | test('Contains returns node with the same data', () => { 19 | const node = new Node(10); 20 | node.insert(5); 21 | node.insert(15); 22 | node.insert(20); 23 | node.insert(0); 24 | node.insert(-5); 25 | node.insert(3); 26 | 27 | const three = node.left.left.right; 28 | expect(node.contains(3)).toEqual(three); 29 | }); 30 | 31 | test('Contains returns null if value not found', () => { 32 | const node = new Node(10); 33 | node.insert(5); 34 | node.insert(15); 35 | node.insert(20); 36 | node.insert(0); 37 | node.insert(-5); 38 | node.insert(3); 39 | 40 | expect(node.contains(9999)).toEqual(null); 41 | }); 42 | -------------------------------------------------------------------------------- /completed_exercises/capitalize/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a string. The function should 3 | // capitalize the first letter of each word in the string then 4 | // return the capitalized string. 5 | // --- Examples 6 | // capitalize('a short sentence') --> 'A Short Sentence' 7 | // capitalize('a lazy fox') --> 'A Lazy Fox' 8 | // capitalize('look, it is working!') --> 'Look, It Is Working!' 9 | 10 | function capitalize(str) { 11 | let result = str[0].toUpperCase(); 12 | 13 | for (let i = 1; i < str.length; i++) { 14 | if (str[i - 1] === ' ') { 15 | result += str[i].toUpperCase(); 16 | } else { 17 | result += str[i]; 18 | } 19 | } 20 | 21 | return result; 22 | } 23 | 24 | module.exports = capitalize; 25 | 26 | // function capitalize(str) { 27 | // const words = []; 28 | // 29 | // for (let word of str.split(' ')) { 30 | // words.push(word[0].toUpperCase() + word.slice(1)); 31 | // } 32 | // 33 | // return words.join(' '); 34 | // } 35 | -------------------------------------------------------------------------------- /completed_exercises/capitalize/test.js: -------------------------------------------------------------------------------- 1 | const capitalize = require('./index'); 2 | 3 | test('Capitalize is a function', () => { 4 | expect(typeof capitalize).toEqual('function'); 5 | }); 6 | 7 | test('capitalizes the first letter of every word in a sentence', () => { 8 | expect(capitalize('hi there, how is it going?')).toEqual( 9 | 'Hi There, How Is It Going?' 10 | ); 11 | }); 12 | 13 | test('capitalizes the first letter', () => { 14 | expect(capitalize('i love breakfast at bill miller bbq')).toEqual( 15 | 'I Love Breakfast At Bill Miller Bbq' 16 | ); 17 | }); 18 | -------------------------------------------------------------------------------- /completed_exercises/chunk/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given an array and chunk size, divide the array into many subarrays 3 | // where each subarray is of length size 4 | // --- Examples 5 | // chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]] 6 | // chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]] 7 | // chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]] 8 | // chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]] 9 | // chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]] 10 | 11 | function chunk(array, size) { 12 | const chunked = []; 13 | let index = 0; 14 | 15 | while (index < array.length) { 16 | chunked.push(array.slice(index, index + size)); 17 | index += size; 18 | } 19 | 20 | return chunked; 21 | } 22 | 23 | module.exports = chunk; 24 | 25 | // function chunk(array, size) { 26 | // const chunked = []; 27 | // 28 | // for (let element of array) { 29 | // const last = chunked[chunked.length - 1]; 30 | // 31 | // if (!last || last.length === size) { 32 | // chunked.push([element]); 33 | // } else { 34 | // last.push(element); 35 | // } 36 | // } 37 | // 38 | // return chunked; 39 | // } 40 | -------------------------------------------------------------------------------- /completed_exercises/chunk/test.js: -------------------------------------------------------------------------------- 1 | const chunk = require('./index'); 2 | 3 | test('function chunk exists', () => { 4 | expect(typeof chunk).toEqual('function'); 5 | }); 6 | 7 | test('chunk divides an array of 10 elements with chunk size 2', () => { 8 | const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 9 | const chunked = chunk(arr, 2); 10 | 11 | expect(chunked).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]); 12 | }); 13 | 14 | test('chunk divides an array of 3 elements with chunk size 1', () => { 15 | const arr = [1, 2, 3]; 16 | const chunked = chunk(arr, 1); 17 | 18 | expect(chunked).toEqual([[1], [2], [3]]); 19 | }); 20 | 21 | test('chunk divides an array of 5 elements with chunk size 3', () => { 22 | const arr = [1, 2, 3, 4, 5]; 23 | const chunked = chunk(arr, 3); 24 | 25 | expect(chunked).toEqual([[1, 2, 3], [4, 5]]); 26 | }); 27 | 28 | test('chunk divides an array of 13 elements with chunk size 5', () => { 29 | const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; 30 | const chunked = chunk(arr, 5); 31 | 32 | expect(chunked).toEqual([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]); 33 | }); 34 | -------------------------------------------------------------------------------- /completed_exercises/circular/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a linked list, return true if the list 3 | // is circular, false if it is not. 4 | // --- Examples 5 | // const l = new List(); 6 | // const a = new Node('a'); 7 | // const b = new Node('b'); 8 | // const c = new Node('c'); 9 | // l.head = a; 10 | // a.next = b; 11 | // b.next = c; 12 | // c.next = b; 13 | // circular(l) // true 14 | 15 | function circular(list) { 16 | let slow = list.getFirst(); 17 | let fast = list.getFirst(); 18 | 19 | while (fast.next && fast.next.next) { 20 | slow = slow.next; 21 | fast = fast.next.next; 22 | 23 | if (slow === fast) { 24 | return true; 25 | } 26 | } 27 | 28 | return false; 29 | } 30 | 31 | module.exports = circular; 32 | -------------------------------------------------------------------------------- /completed_exercises/circular/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor(values = []) { 10 | this.head = null; 11 | 12 | for (let value of values) { 13 | this.insertLast(value); 14 | } 15 | } 16 | 17 | clear() { 18 | this.head = null; 19 | } 20 | 21 | size() { 22 | let counter = 0; 23 | let node = this.head; 24 | 25 | while (node) { 26 | counter++; 27 | node = node.next; 28 | } 29 | 30 | return counter; 31 | } 32 | 33 | getAt(index) { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let counter = 0; 39 | let node = this.head; 40 | while (node) { 41 | if (counter === index) { 42 | return node; 43 | } 44 | node = node.next; 45 | counter++; 46 | } 47 | return null; 48 | } 49 | 50 | insertAt(data, index) { 51 | if (!this.head) { 52 | this.head = new Node(data); 53 | return; 54 | } 55 | 56 | if (index === 0) { 57 | this.head = new Node(data, this.head); 58 | return; 59 | } 60 | 61 | let counter = 1; 62 | let previous = this.head; 63 | let node = this.head.next; 64 | while (node) { 65 | if (counter === index) { 66 | previous.next = new Node(data, node); 67 | return; 68 | } 69 | previous = node; 70 | node = node.next; 71 | counter++; 72 | } 73 | 74 | previous.next = new Node(data, node); 75 | } 76 | 77 | removeFirst() { 78 | if (!this.head) { 79 | return; 80 | } 81 | 82 | this.head = this.head.next; 83 | } 84 | 85 | removeLast() { 86 | if (!this.head) { 87 | return; 88 | } 89 | 90 | if (!this.head.next) { 91 | this.head = null; 92 | return; 93 | } 94 | 95 | let previous = this.head; 96 | let node = this.head.next; 97 | while (node.next) { 98 | previous = node; 99 | node = node.next; 100 | } 101 | previous.next = null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | let counter = 0; 110 | let node = this.head; 111 | while (node) { 112 | if (counter === index - 1) { 113 | if (node.next) { 114 | return (node.next = node.next.next); 115 | } else { 116 | return (node.next = null); 117 | } 118 | } 119 | node = node.next; 120 | counter++; 121 | } 122 | } 123 | 124 | getFirst() { 125 | return this.head; 126 | } 127 | 128 | insertFirst(data) { 129 | this.head = new Node(data, this.getFirst()); 130 | } 131 | 132 | getLast() { 133 | if (!this.head) { 134 | return null; 135 | } 136 | 137 | let node = this.head; 138 | while (node.next) { 139 | node = node.next; 140 | } 141 | 142 | return node; 143 | } 144 | 145 | insertLast(data) { 146 | const last = this.getLast(); 147 | 148 | if (last) { 149 | last.next = new Node(data); 150 | return last.next; 151 | } else { 152 | this.head = new Node(data); 153 | return this.head; 154 | } 155 | } 156 | 157 | forEach(fn) { 158 | if (!this.head) { 159 | return null; 160 | } 161 | 162 | let node = this.head; 163 | while (node) { 164 | fn(node); 165 | node = node.next; 166 | } 167 | } 168 | 169 | *[Symbol.iterator]() { 170 | let node = this.head; 171 | while (node) { 172 | yield node; 173 | node = node.next; 174 | } 175 | } 176 | } 177 | 178 | module.exports = { Node, LinkedList }; 179 | -------------------------------------------------------------------------------- /completed_exercises/circular/test.js: -------------------------------------------------------------------------------- 1 | const circular = require('./index'); 2 | const L = require('./linkedlist'); 3 | const List = L.LinkedList; 4 | const Node = L.Node; 5 | 6 | test('circular function is defined', () => { 7 | expect(typeof circular).toEqual('function'); 8 | }); 9 | 10 | test('circular detects circular linked lists', () => { 11 | const l = new List(); 12 | const a = new Node('a'); 13 | const b = new Node('b'); 14 | const c = new Node('c'); 15 | 16 | l.head = a; 17 | a.next = b; 18 | b.next = c; 19 | c.next = b; 20 | 21 | expect(circular(l)).toEqual(true); 22 | }); 23 | 24 | test('circular detects circular linked lists linked at the head', () => { 25 | const l = new List(); 26 | const a = new Node('a'); 27 | const b = new Node('b'); 28 | const c = new Node('c'); 29 | 30 | l.head = a; 31 | a.next = b; 32 | b.next = c; 33 | c.next = a; 34 | 35 | expect(circular(l)).toEqual(true); 36 | }); 37 | 38 | test('circular detects non-circular linked lists', () => { 39 | const l = new List(); 40 | const a = new Node('a'); 41 | const b = new Node('b'); 42 | const c = new Node('c'); 43 | 44 | l.head = a; 45 | a.next = b; 46 | b.next = c; 47 | c.next = null; 48 | 49 | expect(circular(l)).toEqual(false); 50 | }); 51 | -------------------------------------------------------------------------------- /completed_exercises/events/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Click the button

6 | 7 | 19 | 20 | -------------------------------------------------------------------------------- /completed_exercises/events/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Create an 'eventing' library out of the 3 | // Events class. The Events class should 4 | // have methods 'on', 'trigger', and 'off'. 5 | 6 | class Events { 7 | constructor() { 8 | this.events = {}; 9 | } 10 | 11 | // Register an event handler 12 | on(eventName, callback) { 13 | if (this.events[eventName]) { 14 | this.events[eventName].push(callback); 15 | } else { 16 | this.events[eventName] = [callback]; 17 | } 18 | } 19 | 20 | // Trigger all callbacks associated 21 | // with a given eventName 22 | trigger(eventName) { 23 | if (this.events[eventName]) { 24 | for (let cb of this.events[eventName]) { 25 | cb(); 26 | } 27 | } 28 | } 29 | 30 | // Remove all event handlers associated 31 | // with the given eventName 32 | off(eventName) { 33 | delete this.events[eventName]; 34 | } 35 | } 36 | 37 | module.exports = Events; 38 | -------------------------------------------------------------------------------- /completed_exercises/events/test.js: -------------------------------------------------------------------------------- 1 | const Events = require('./index'); 2 | 3 | test('Events can be registered then triggered', () => { 4 | const events = new Events(); 5 | 6 | const cb1 = jest.fn(); 7 | 8 | events.on('click', cb1); 9 | events.trigger('click'); 10 | 11 | expect(cb1.mock.calls.length).toBe(1); 12 | }); 13 | 14 | test('Multiple events can be registered then triggered', () => { 15 | const events = new Events(); 16 | 17 | const cb1 = jest.fn(); 18 | const cb2 = jest.fn(); 19 | 20 | events.on('click', cb1); 21 | events.on('click', cb2); 22 | events.trigger('click'); 23 | 24 | expect(cb1.mock.calls.length).toBe(1); 25 | expect(cb2.mock.calls.length).toBe(1); 26 | }); 27 | 28 | test('Events can be triggered multiple times', () => { 29 | const events = new Events(); 30 | 31 | const cb1 = jest.fn(); 32 | const cb2 = jest.fn(); 33 | 34 | events.on('click', cb1); 35 | events.trigger('click'); 36 | events.on('click', cb2); 37 | events.trigger('click'); 38 | events.trigger('click'); 39 | 40 | expect(cb1.mock.calls.length).toBe(3); 41 | expect(cb2.mock.calls.length).toBe(2); 42 | }); 43 | 44 | test('Events can have different names', () => { 45 | const events = new Events(); 46 | 47 | const cb1 = jest.fn(); 48 | const cb2 = jest.fn(); 49 | 50 | events.on('click', cb1); 51 | events.trigger('click'); 52 | events.on('hover', cb2); 53 | events.trigger('click'); 54 | events.trigger('hover'); 55 | 56 | expect(cb1.mock.calls.length).toBe(2); 57 | expect(cb2.mock.calls.length).toBe(1); 58 | }); 59 | 60 | test('Events can be toggled off', () => { 61 | const events = new Events(); 62 | 63 | const cb1 = jest.fn(); 64 | const cb2 = jest.fn(); 65 | 66 | events.on('hover', cb2); 67 | 68 | events.on('click', cb1); 69 | events.trigger('click'); 70 | events.off('click'); 71 | events.trigger('click'); 72 | 73 | events.trigger('hover'); 74 | 75 | expect(cb1.mock.calls.length).toBe(1); 76 | expect(cb2.mock.calls.length).toBe(1); 77 | }); 78 | -------------------------------------------------------------------------------- /completed_exercises/fib/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Print out the n-th entry in the fibonacci series. 3 | // The fibonacci series is an ordering of numbers where 4 | // each number is the sum of the preceeding two. 5 | // For example, the sequence 6 | // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 7 | // forms the first ten entries of the fibonacci series. 8 | // Example: 9 | // fib(4) === 3 10 | 11 | function memoize(fn) { 12 | const cache = {}; 13 | return function(...args) { 14 | if (cache[args]) { 15 | return cache[args]; 16 | } 17 | 18 | const result = fn.apply(this, args); 19 | cache[args] = result; 20 | 21 | return result; 22 | }; 23 | } 24 | 25 | function slowFib(n) { 26 | if (n < 2) { 27 | return n; 28 | } 29 | 30 | return fib(n - 1) + fib(n - 2); 31 | } 32 | 33 | const fib = memoize(slowFib); 34 | 35 | module.exports = fib; 36 | 37 | // function fib(n) { 38 | // const result = [0, 1]; 39 | // 40 | // for (let i = 2; i <= n; i++) { 41 | // const a = result[i - 1]; 42 | // const b = result[i - 2]; 43 | // 44 | // result.push(a + b); 45 | // } 46 | // 47 | // return result[n]; 48 | // } 49 | -------------------------------------------------------------------------------- /completed_exercises/fib/test.js: -------------------------------------------------------------------------------- 1 | const fib = require('./index'); 2 | 3 | test('Fib function is defined', () => { 4 | expect(typeof fib).toEqual('function'); 5 | }); 6 | 7 | test('calculates correct fib value for 1', () => { 8 | expect(fib(1)).toEqual(1); 9 | }); 10 | 11 | test('calculates correct fib value for 2', () => { 12 | expect(fib(2)).toEqual(1); 13 | }); 14 | 15 | test('calculates correct fib value for 3', () => { 16 | expect(fib(3)).toEqual(2); 17 | }); 18 | 19 | test('calculates correct fib value for 4', () => { 20 | expect(fib(4)).toEqual(3); 21 | }); 22 | 23 | test('calculates correct fib value for 15', () => { 24 | expect(fib(39)).toEqual(63245986); 25 | }); 26 | -------------------------------------------------------------------------------- /completed_exercises/fizzbuzz/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a program that console logs the numbers 3 | // from 1 to n. But for multiples of three print 4 | // “fizz” instead of the number and for the multiples 5 | // of five print “buzz”. For numbers which are multiples 6 | // of both three and five print “fizzbuzz”. 7 | // --- Example 8 | // fizzBuzz(5); 9 | // 1 10 | // 2 11 | // fizz 12 | // 4 13 | // buzz 14 | 15 | function fizzBuzz(n) { 16 | for (let i = 1; i <= n; i++) { 17 | // Is the number a multiple of 3 and 5? 18 | if (i % 3 === 0 && i % 5 === 0) { 19 | console.log('fizzbuzz'); 20 | } else if (i % 3 === 0) { 21 | // Is the number a multiple of 3? 22 | console.log('fizz'); 23 | } else if (i % 5 === 0) { 24 | console.log('buzz'); 25 | } else { 26 | console.log(i); 27 | } 28 | } 29 | } 30 | 31 | module.exports = fizzBuzz; 32 | -------------------------------------------------------------------------------- /completed_exercises/fizzbuzz/test.js: -------------------------------------------------------------------------------- 1 | const fizzBuzz = require('./index'); 2 | 3 | test('fizzBuzz function is defined', () => { 4 | expect(fizzBuzz).toBeDefined(); 5 | }); 6 | 7 | test('Calling fizzbuzz with `5` prints out 5 statements', () => { 8 | fizzBuzz(5); 9 | 10 | expect(console.log.mock.calls.length).toEqual(5); 11 | }); 12 | 13 | test('Calling fizzbuzz with 15 prints out the correct values', () => { 14 | fizzBuzz(15); 15 | 16 | expect(console.log.mock.calls[0][0]).toEqual(1); 17 | expect(console.log.mock.calls[1][0]).toEqual(2); 18 | expect(console.log.mock.calls[2][0]).toEqual('fizz'); 19 | expect(console.log.mock.calls[3][0]).toEqual(4); 20 | expect(console.log.mock.calls[4][0]).toEqual('buzz'); 21 | expect(console.log.mock.calls[5][0]).toEqual('fizz'); 22 | expect(console.log.mock.calls[6][0]).toEqual(7); 23 | expect(console.log.mock.calls[7][0]).toEqual(8); 24 | expect(console.log.mock.calls[8][0]).toEqual('fizz'); 25 | expect(console.log.mock.calls[9][0]).toEqual('buzz'); 26 | expect(console.log.mock.calls[10][0]).toEqual(11); 27 | expect(console.log.mock.calls[11][0]).toEqual('fizz'); 28 | expect(console.log.mock.calls[12][0]).toEqual(13); 29 | expect(console.log.mock.calls[13][0]).toEqual(14); 30 | expect(console.log.mock.calls[14][0]).toEqual('fizzbuzz'); 31 | }); 32 | 33 | beforeEach(() => { 34 | jest.spyOn(console, 'log').mockImplementation(() => {}); 35 | }); 36 | 37 | afterEach(() => { 38 | console.log.mockRestore(); 39 | }); 40 | -------------------------------------------------------------------------------- /completed_exercises/fromlast/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a linked list and integer n, return the element n 3 | // spaces from the last node in the list. Do not call the 4 | // 'size' method of the linked list. Assume that n will always 5 | // be less than the length of the list. 6 | // --- Examples 7 | // const list = new List(); 8 | // list.insertLast('a'); 9 | // list.insertLast('b'); 10 | // list.insertLast('c'); 11 | // list.insertLast('d'); 12 | // fromLast(list, 2).data // 'b' 13 | 14 | function fromLast(list, n) { 15 | let slow = list.getFirst(); 16 | let fast = list.getFirst(); 17 | 18 | while (n > 0) { 19 | fast = fast.next; 20 | n--; 21 | } 22 | 23 | while (fast.next) { 24 | slow = slow.next; 25 | fast = fast.next; 26 | } 27 | 28 | return slow; 29 | } 30 | 31 | module.exports = fromLast; 32 | -------------------------------------------------------------------------------- /completed_exercises/fromlast/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor() { 10 | this.head = null; 11 | } 12 | 13 | insertFirst(data) { 14 | this.head = new Node(data, this.head); 15 | } 16 | 17 | size() { 18 | let counter = 0; 19 | let node = this.head; 20 | 21 | while (node) { 22 | counter++; 23 | node = node.next; 24 | } 25 | 26 | return counter; 27 | } 28 | 29 | getFirst() { 30 | return this.head; 31 | } 32 | 33 | getLast() { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let node = this.head; 39 | while (node) { 40 | if (!node.next) { 41 | return node; 42 | } 43 | node = node.next; 44 | } 45 | } 46 | 47 | clear() { 48 | this.head = null; 49 | } 50 | 51 | removeFirst() { 52 | if (!this.head) { 53 | return; 54 | } 55 | 56 | this.head = this.head.next; 57 | } 58 | 59 | removeLast() { 60 | if (!this.head) { 61 | return; 62 | } 63 | 64 | if (!this.head.next) { 65 | this.head = null; 66 | return; 67 | } 68 | 69 | let previous = this.head; 70 | let node = this.head.next; 71 | while (node.next) { 72 | previous = node; 73 | node = node.next; 74 | } 75 | previous.next = null; 76 | } 77 | 78 | insertLast(data) { 79 | const last = this.getLast(); 80 | 81 | if (last) { 82 | // There are some existing nodes in our chain 83 | last.next = new Node(data); 84 | } else { 85 | // The chain is empty! 86 | this.head = new Node(data); 87 | } 88 | } 89 | 90 | getAt(index) { 91 | let counter = 0; 92 | let node = this.head; 93 | while (node) { 94 | if (counter === index) { 95 | return node; 96 | } 97 | 98 | counter++; 99 | node = node.next; 100 | } 101 | return null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | if (index === 0) { 110 | this.head = this.head.next; 111 | return; 112 | } 113 | 114 | const previous = this.getAt(index - 1); 115 | if (!previous || !previous.next) { 116 | return; 117 | } 118 | previous.next = previous.next.next; 119 | } 120 | 121 | insertAt(data, index) { 122 | if (!this.head) { 123 | this.head = new Node(data); 124 | return; 125 | } 126 | 127 | if (index === 0) { 128 | this.head = new Node(data, this.head); 129 | return; 130 | } 131 | 132 | const previous = this.getAt(index - 1) || this.getLast(); 133 | const node = new Node(data, previous.next); 134 | previous.next = node; 135 | } 136 | 137 | forEach(fn) { 138 | let node = this.head; 139 | let counter = 0; 140 | while (node) { 141 | fn(node, counter); 142 | node = node.next; 143 | counter++; 144 | } 145 | } 146 | 147 | *[Symbol.iterator]() { 148 | let node = this.head; 149 | while (node) { 150 | yield node; 151 | node = node.next; 152 | } 153 | } 154 | } 155 | 156 | module.exports = { Node, LinkedList }; 157 | -------------------------------------------------------------------------------- /completed_exercises/fromlast/test.js: -------------------------------------------------------------------------------- 1 | const fromLast = require('./index'); 2 | const L = require('./linkedlist'); 3 | const List = L.LinkedList; 4 | const Node = L.Node; 5 | 6 | test('fromLast is a function', () => { 7 | expect(typeof fromLast).toEqual('function'); 8 | }); 9 | 10 | test('fromLast returns the node n elements from the end', () => { 11 | const l = new List(); 12 | 13 | l.insertLast('a'); 14 | l.insertLast('b'); 15 | l.insertLast('c'); 16 | l.insertLast('d'); 17 | l.insertLast('e'); 18 | 19 | expect(fromLast(l, 3).data).toEqual('b'); 20 | }); 21 | -------------------------------------------------------------------------------- /completed_exercises/levelwidth/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given the root node of a tree, return 3 | // an array where each element is the width 4 | // of the tree at each level. 5 | // --- Example 6 | // Given: 7 | // 0 8 | // / | \ 9 | // 1 2 3 10 | // | | 11 | // 4 5 12 | // Answer: [1, 3, 2] 13 | 14 | function levelWidth(root) { 15 | const arr = [root, 's']; 16 | const counters = [0]; 17 | 18 | while (arr.length > 1) { 19 | const node = arr.shift(); 20 | 21 | if (node === 's') { 22 | counters.push(0); 23 | arr.push('s'); 24 | } else { 25 | arr.push(...node.children); 26 | counters[counters.length - 1]++; 27 | } 28 | } 29 | 30 | return counters; 31 | } 32 | 33 | module.exports = levelWidth; 34 | -------------------------------------------------------------------------------- /completed_exercises/levelwidth/node.js: -------------------------------------------------------------------------------- 1 | module.exports = class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.children = []; 5 | } 6 | 7 | add(data) { 8 | this.children.push(new Node(data)); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /completed_exercises/levelwidth/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./node'); 2 | const levelWidth = require('./index'); 3 | 4 | test('levelWidth is a function', () => { 5 | expect(typeof levelWidth).toEqual('function'); 6 | }); 7 | 8 | test('levelWidth returns number of nodes at widest point', () => { 9 | const root = new Node(0); 10 | root.add(1); 11 | root.add(2); 12 | root.add(3); 13 | root.children[0].add(4); 14 | root.children[2].add(5); 15 | 16 | expect(levelWidth(root)).toEqual([1, 3, 2]); 17 | }); 18 | 19 | test('levelWidth returns number of nodes at widest point', () => { 20 | const root = new Node(0); 21 | root.add(1); 22 | root.children[0].add(2); 23 | root.children[0].add(3); 24 | root.children[0].children[0].add(4); 25 | 26 | expect(levelWidth(root)).toEqual([1, 1, 2, 1]); 27 | }); 28 | -------------------------------------------------------------------------------- /completed_exercises/linkedlist/directions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 |

Node Class API

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 35 | 44 | 45 | 46 |
FunctionArgumentsReturnsDirectionsExample
constructor(Data, Node)Node 28 | Creates a class instance to represent a node. The node should 29 | have two properties, 'data' and 'next'. Accept both 30 | of these as arguments to the 'Node' constructor, then 31 | assign them to the instance as properties 'data' and 'next'. 32 | If 'next' is not provided to the constructor, then default its 33 | value to be 'null'. 34 | 36 |
 37 |             const n = new Node('Hi');
 38 |             n.data // 'Hi'
 39 |             n.next // null
 40 |             const n2 = new Node('There', n);
 41 |             n.next // returns n
 42 |           
43 |
47 | 48 |

LinkedList Class API

49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 87 | 93 | 94 | 95 | 96 | 97 | 98 | 101 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 126 | 127 | 128 | 131 | 134 | 137 | 140 | 148 | 149 | 150 | 153 | 156 | 159 | 162 | 171 | 172 | 173 | 176 | 179 | 182 | 186 | 195 | 196 | 197 | 200 | 203 | 206 | 209 | 219 | 220 | 221 | 224 | 227 | 230 | 233 | 242 | 243 | 244 | 247 | 250 | 253 | 256 | 265 | 266 | 267 | 270 | 273 | 276 | 279 | 289 | 290 | 291 | 294 | 297 | 300 | 305 | 315 | 316 | 317 | 320 | 323 | 326 | 330 | 345 | 346 | 347 | 350 | 353 | 356 | 359 | 375 | 376 | 377 |
FunctionArgumentsReturnsDirectionsExample
constructor-(LinkedList) 65 | Create a class to represent a linked list. When created, 66 | a linked list should have *no* head node associated with it. 67 | The LinkedList instance will have one property, 'head', which 68 | is a reference to the first node of the linked list. By default 69 | 'head' should be 'null'. 70 | 72 |
 73 |             const list = new LinkedList();
 74 |             list.head // null
 75 |           
76 |
insertFirst(data)- 83 | Creates a new Node from argument 'data' and assigns the resulting 84 | node to the 'head' property. Make sure to handle the case in which 85 | the linked list already has a node assigned to the 'head' property. 86 | 88 |
 89 |             const list = new LinkedList();
 90 |             list.insertFirst('Hi There'); // List has one node
 91 |           
92 |
size-(integer) 99 | Returns the number of nodes in the linked list. 100 | 102 |
103 |             const list = new LinkedList();
104 |             list.insertFirst('a');
105 |             list.insertFirst('b');
106 |             list.insertFirst('c');
107 |             list.size(); // returns 3
108 |           
109 |
getFirst-(Node) 116 | Returns the first node of the linked list. 117 | 119 |
120 |             const list = new LinkedList();
121 |             list.insertFirst('a');
122 |             list.insertFirst('b');
123 |             list.getFirst(); // returns Node instance with data 'a'
124 |           
125 |
129 | getLast 130 | 132 | - 133 | 135 | (Node) 136 | 138 | Returns the last node of the linked list 139 | 141 |
142 |             const list = new LinkedList();
143 |             list.insertFirst('a');
144 |             list.insertFirst('b');
145 |             list.getLast(); // returns node with data 'a'
146 |           
147 |
151 | clear 152 | 154 | - 155 | 157 | - 158 | 160 | Empties the linked list of any nodes. 161 | 163 |
164 |             const list = new LinkedList();
165 |             list.insertFirst('a');
166 |             list.insertFirst('b');
167 |             list.clear();
168 |             list.size(); // returns 0
169 |           
170 |
174 | removeFirst 175 | 177 | - 178 | 180 | - 181 | 183 | Removes only the first node of the linked list. The list's head should 184 | now be the second element. 185 | 187 |
188 |             const list = new LinkedList();
189 |             list.insertFirst('a');
190 |             list.insertFirst('b');
191 |             list.removeFirst();
192 |             list.getFirst(); // returns node with data 'a'
193 |           
194 |
198 | removeLast 199 | 201 | - 202 | 204 | - 205 | 207 | Removes the last node of the chain 208 | 210 |
211 |             const list = new LinkedList();
212 |             list.insertFirst('a');
213 |             list.insertFirst('b');
214 |             list.removeLast();
215 |             list.size(); // returns 1
216 |             list.getLast(); // returns node with data of 'b'
217 |           
218 |
222 | insertLast 223 | 225 | (Data) 226 | 228 | - 229 | 231 | Inserts a new node with provided data at the end of the chain 232 | 234 |
235 |             const list = new LinkedList();
236 |             list.insertFirst('a');
237 |             list.insertFirst('b');
238 |             list.insertLast('c');
239 |             list.getLast(); // returns node with data 'C'
240 |           
241 |
245 | getAt 246 | 248 | (integer) 249 | 251 | (Node) 252 | 254 | Returns the node at the provided index 255 | 257 |
258 |             const list = new List();
259 |             list.insertFirst('a');
260 |             list.insertFirst('b');
261 |             list.insertFirst('c');
262 |             list.getAt(1); // returns node with data 'b'
263 |           
264 |
268 | removeAt 269 | 271 | (integer) 272 | 274 | - 275 | 277 | Removes node at the provided index 278 | 280 |
281 |             const list = new List();
282 |             list.insertFirst('a');
283 |             list.insertFirst('b');
284 |             list.insertFirst('c');
285 |             list.removeAt(1);
286 |             list.getAt(1); // returns node with data 'a'
287 |           
288 |
292 | insertAt 293 | 295 | (Data, integer) 296 | 298 | - 299 | 301 | Create an insert a new node at provided index. 302 | If index is out of bounds, add the node to the end 303 | of the list. 304 | 306 |
307 |             const list = new List();
308 |             list.insertFirst('a');
309 |             list.insertFirst('b');
310 |             list.insertFirst('c');
311 |             list.insertAt('Hi', 1)
312 |             list.getAt(1); // returns node with data 'Hi'
313 |           
314 |
318 | forEach 319 | 321 | (function) 322 | 324 | - 325 | 327 | Calls the provided function with every node of the chain and the index 328 | of the node. 329 | 331 |
332 |             const list = new List();
333 | 
334 |             list.insertLast(1);
335 |             list.insertLast(2);
336 |             list.insertLast(3);
337 |             list.insertLast(4);
338 | 
339 |             list.forEach((node, index) => {
340 |               node.data += 10;
341 |             });
342 |             list.getAt(0); // Returns node with data '11'
343 |           
344 |
348 | for...of Loop 349 | 351 | - 352 | 354 | - 355 | 357 | Linked list should be compatible as the subject of a 'for...of' loop 358 | 360 |
361 |             const list = new List();
362 | 
363 |             list.insertLast(1);
364 |             list.insertLast(2);
365 |             list.insertLast(3);
366 |             list.insertLast(4);
367 | 
368 |             for (let node of list) {
369 |               node.data += 10;
370 |             }
371 | 
372 |             node.getAt(1); // returns node with data 11
373 |           
374 |
378 | 379 | -------------------------------------------------------------------------------- /completed_exercises/linkedlist/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement classes Node and Linked Lists 3 | // See 'directions' document 4 | 5 | class Node { 6 | constructor(data, next = null) { 7 | this.data = data; 8 | this.next = next; 9 | } 10 | } 11 | 12 | class LinkedList { 13 | constructor() { 14 | this.head = null; 15 | } 16 | 17 | insertFirst(data) { 18 | this.head = new Node(data, this.head); 19 | } 20 | 21 | size() { 22 | let counter = 0; 23 | let node = this.head; 24 | 25 | while (node) { 26 | counter++; 27 | node = node.next; 28 | } 29 | 30 | return counter; 31 | } 32 | 33 | getFirst() { 34 | return this.head; 35 | } 36 | 37 | getLast() { 38 | if (!this.head) { 39 | return null; 40 | } 41 | 42 | let node = this.head; 43 | while (node) { 44 | if (!node.next) { 45 | return node; 46 | } 47 | node = node.next; 48 | } 49 | } 50 | 51 | clear() { 52 | this.head = null; 53 | } 54 | 55 | removeFirst() { 56 | if (!this.head) { 57 | return; 58 | } 59 | 60 | this.head = this.head.next; 61 | } 62 | 63 | removeLast() { 64 | if (!this.head) { 65 | return; 66 | } 67 | 68 | if (!this.head.next) { 69 | this.head = null; 70 | return; 71 | } 72 | 73 | let previous = this.head; 74 | let node = this.head.next; 75 | while (node.next) { 76 | previous = node; 77 | node = node.next; 78 | } 79 | previous.next = null; 80 | } 81 | 82 | insertLast(data) { 83 | const last = this.getLast(); 84 | 85 | if (last) { 86 | // There are some existing nodes in our chain 87 | last.next = new Node(data); 88 | } else { 89 | // The chain is empty! 90 | this.head = new Node(data); 91 | } 92 | } 93 | 94 | getAt(index) { 95 | let counter = 0; 96 | let node = this.head; 97 | while (node) { 98 | if (counter === index) { 99 | return node; 100 | } 101 | 102 | counter++; 103 | node = node.next; 104 | } 105 | return null; 106 | } 107 | 108 | removeAt(index) { 109 | if (!this.head) { 110 | return; 111 | } 112 | 113 | if (index === 0) { 114 | this.head = this.head.next; 115 | return; 116 | } 117 | 118 | const previous = this.getAt(index - 1); 119 | if (!previous || !previous.next) { 120 | return; 121 | } 122 | previous.next = previous.next.next; 123 | } 124 | 125 | insertAt(data, index) { 126 | if (!this.head) { 127 | this.head = new Node(data); 128 | return; 129 | } 130 | 131 | if (index === 0) { 132 | this.head = new Node(data, this.head); 133 | return; 134 | } 135 | 136 | const previous = this.getAt(index - 1) || this.getLast(); 137 | const node = new Node(data, previous.next); 138 | previous.next = node; 139 | } 140 | 141 | forEach(fn) { 142 | let node = this.head; 143 | let counter = 0; 144 | while (node) { 145 | fn(node, counter); 146 | node = node.next; 147 | counter++; 148 | } 149 | } 150 | 151 | *[Symbol.iterator]() { 152 | let node = this.head; 153 | while (node) { 154 | yield node; 155 | node = node.next; 156 | } 157 | } 158 | } 159 | 160 | module.exports = { Node, LinkedList }; 161 | -------------------------------------------------------------------------------- /completed_exercises/linkedlist/test.js: -------------------------------------------------------------------------------- 1 | const L = require('./index'); 2 | const List = L.LinkedList; 3 | const Node = L.Node; 4 | 5 | test('List is a class', () => { 6 | expect(typeof List.prototype.constructor).toEqual('function'); 7 | }); 8 | 9 | test('Node is a class', () => { 10 | expect(typeof Node.prototype.constructor).toEqual('function'); 11 | }); 12 | 13 | describe('A Node', () => { 14 | test('has properties "data" and "next"', () => { 15 | const node = new Node('a', 'b'); 16 | expect(node.data).toEqual('a'); 17 | expect(node.next).toEqual('b'); 18 | }); 19 | }); 20 | 21 | describe('Insert First', () => { 22 | test('appends a node to the start of the list', () => { 23 | const l = new List(); 24 | l.insertFirst(1); 25 | expect(l.head.data).toEqual(1); 26 | l.insertFirst(2); 27 | expect(l.head.data).toEqual(2); 28 | }); 29 | }); 30 | 31 | describe('Size', () => { 32 | test('returns the number of items in the linked list', () => { 33 | const l = new List(); 34 | expect(l.size()).toEqual(0); 35 | l.insertFirst(1); 36 | l.insertFirst(1); 37 | l.insertFirst(1); 38 | l.insertFirst(1); 39 | expect(l.size()).toEqual(4); 40 | }); 41 | }); 42 | 43 | describe('GetFirst', () => { 44 | test('returns the first element', () => { 45 | const l = new List(); 46 | l.insertFirst(1); 47 | expect(l.getFirst().data).toEqual(1); 48 | l.insertFirst(2); 49 | expect(l.getFirst().data).toEqual(2); 50 | }); 51 | }); 52 | 53 | describe('GetLast', () => { 54 | test('returns the last element', () => { 55 | const l = new List(); 56 | l.insertFirst(2); 57 | expect(l.getLast()).toEqual({ data: 2, next: null }); 58 | l.insertFirst(1); 59 | expect(l.getLast()).toEqual({ data: 2, next: null }); 60 | }); 61 | }); 62 | 63 | describe('Clear', () => { 64 | test('empties out the list', () => { 65 | const l = new List(); 66 | expect(l.size()).toEqual(0); 67 | l.insertFirst(1); 68 | l.insertFirst(1); 69 | l.insertFirst(1); 70 | l.insertFirst(1); 71 | expect(l.size()).toEqual(4); 72 | l.clear(); 73 | expect(l.size()).toEqual(0); 74 | }); 75 | }); 76 | 77 | describe('RemoveFirst', () => { 78 | test('removes the first node when the list has a size of one', () => { 79 | const l = new List(); 80 | l.insertFirst('a'); 81 | l.removeFirst(); 82 | expect(l.size()).toEqual(0); 83 | expect(l.getFirst()).toEqual(null); 84 | }); 85 | 86 | test('removes the first node when the list has a size of three', () => { 87 | const l = new List(); 88 | l.insertFirst('c'); 89 | l.insertFirst('b'); 90 | l.insertFirst('a'); 91 | l.removeFirst(); 92 | expect(l.size()).toEqual(2); 93 | expect(l.getFirst().data).toEqual('b'); 94 | l.removeFirst(); 95 | expect(l.size()).toEqual(1); 96 | expect(l.getFirst().data).toEqual('c'); 97 | }); 98 | }); 99 | 100 | describe('RemoveLast', () => { 101 | test('RemoveLast removes the last node when list is empty', () => { 102 | const l = new List(); 103 | expect(() => { 104 | l.removeLast(); 105 | }).not.toThrow(); 106 | }); 107 | 108 | test('RemoveLast removes the last node when list is length 1', () => { 109 | const l = new List(); 110 | l.insertFirst('a'); 111 | l.removeLast(); 112 | expect(l.head).toEqual(null); 113 | }); 114 | 115 | test('RemoveLast removes the last node when list is length 2', () => { 116 | const l = new List(); 117 | l.insertFirst('b'); 118 | l.insertFirst('a'); 119 | 120 | l.removeLast(); 121 | 122 | expect(l.size()).toEqual(1); 123 | expect(l.head.data).toEqual('a'); 124 | }); 125 | 126 | test('RemoveLast removes the last node when list is length 3', () => { 127 | const l = new List(); 128 | l.insertFirst('c'); 129 | l.insertFirst('b'); 130 | l.insertFirst('a'); 131 | l.removeLast(); 132 | 133 | expect(l.size()).toEqual(2); 134 | expect(l.getLast().data).toEqual('b'); 135 | }); 136 | }); 137 | 138 | describe('InsertLast', () => { 139 | test('adds to the end of the list', () => { 140 | const l = new List(); 141 | l.insertFirst('a'); 142 | 143 | l.insertLast('b'); 144 | 145 | expect(l.size()).toEqual(2); 146 | expect(l.getLast().data).toEqual('b'); 147 | }); 148 | }); 149 | 150 | describe('GetAt', () => { 151 | test('returns the node at given index', () => { 152 | const l = new List(); 153 | expect(l.getAt(10)).toEqual(null); 154 | 155 | l.insertLast(1); 156 | l.insertLast(2); 157 | l.insertLast(3); 158 | l.insertLast(4); 159 | 160 | expect(l.getAt(0).data).toEqual(1); 161 | expect(l.getAt(1).data).toEqual(2); 162 | expect(l.getAt(2).data).toEqual(3); 163 | expect(l.getAt(3).data).toEqual(4); 164 | }); 165 | }); 166 | 167 | describe('RemoveAt', () => { 168 | test('removeAt doesnt crash on an empty list', () => { 169 | const l = new List(); 170 | expect(() => { 171 | l.removeAt(0); 172 | l.removeAt(1); 173 | l.removeAt(2); 174 | }).not.toThrow(); 175 | }); 176 | 177 | test('removeAt doesnt crash on an index out of bounds', () => { 178 | const l = new List(); 179 | expect(() => { 180 | const l = new List(); 181 | l.insertFirst('a'); 182 | l.removeAt(1); 183 | }).not.toThrow(); 184 | }); 185 | 186 | test('removeAt deletes the first node', () => { 187 | const l = new List(); 188 | l.insertLast(1); 189 | l.insertLast(2); 190 | l.insertLast(3); 191 | l.insertLast(4); 192 | expect(l.getAt(0).data).toEqual(1); 193 | l.removeAt(0); 194 | expect(l.getAt(0).data).toEqual(2); 195 | }); 196 | 197 | test('removeAt deletes the node at the given index', () => { 198 | const l = new List(); 199 | l.insertLast(1); 200 | l.insertLast(2); 201 | l.insertLast(3); 202 | l.insertLast(4); 203 | expect(l.getAt(1).data).toEqual(2); 204 | l.removeAt(1); 205 | expect(l.getAt(1).data).toEqual(3); 206 | }); 207 | 208 | test('removeAt works on the last node', () => { 209 | const l = new List(); 210 | l.insertLast(1); 211 | l.insertLast(2); 212 | l.insertLast(3); 213 | l.insertLast(4); 214 | expect(l.getAt(3).data).toEqual(4); 215 | l.removeAt(3); 216 | expect(l.getAt(3)).toEqual(null); 217 | }); 218 | }); 219 | 220 | describe('InsertAt', () => { 221 | test('inserts a new node with data at the 0 index when the list is empty', () => { 222 | const l = new List(); 223 | l.insertAt('hi', 0); 224 | expect(l.getFirst().data).toEqual('hi'); 225 | }); 226 | 227 | test('inserts a new node with data at the 0 index when the list has elements', () => { 228 | const l = new List(); 229 | l.insertLast('a'); 230 | l.insertLast('b'); 231 | l.insertLast('c'); 232 | l.insertAt('hi', 0); 233 | expect(l.getAt(0).data).toEqual('hi'); 234 | expect(l.getAt(1).data).toEqual('a'); 235 | expect(l.getAt(2).data).toEqual('b'); 236 | expect(l.getAt(3).data).toEqual('c'); 237 | }); 238 | 239 | test('inserts a new node with data at a middle index', () => { 240 | const l = new List(); 241 | l.insertLast('a'); 242 | l.insertLast('b'); 243 | l.insertLast('c'); 244 | l.insertLast('d'); 245 | l.insertAt('hi', 2); 246 | expect(l.getAt(0).data).toEqual('a'); 247 | expect(l.getAt(1).data).toEqual('b'); 248 | expect(l.getAt(2).data).toEqual('hi'); 249 | expect(l.getAt(3).data).toEqual('c'); 250 | expect(l.getAt(4).data).toEqual('d'); 251 | }); 252 | 253 | test('inserts a new node with data at a last index', () => { 254 | const l = new List(); 255 | l.insertLast('a'); 256 | l.insertLast('b'); 257 | l.insertAt('hi', 2); 258 | expect(l.getAt(0).data).toEqual('a'); 259 | expect(l.getAt(1).data).toEqual('b'); 260 | expect(l.getAt(2).data).toEqual('hi'); 261 | }); 262 | 263 | test('insert a new node when index is out of bounds', () => { 264 | const l = new List(); 265 | l.insertLast('a'); 266 | l.insertLast('b'); 267 | l.insertAt('hi', 30); 268 | 269 | expect(l.getAt(0).data).toEqual('a'); 270 | expect(l.getAt(1).data).toEqual('b'); 271 | expect(l.getAt(2).data).toEqual('hi'); 272 | }); 273 | }); 274 | 275 | describe('ForEach', () => { 276 | test('applies a transform to each node', () => { 277 | const l = new List(); 278 | 279 | l.insertLast(1); 280 | l.insertLast(2); 281 | l.insertLast(3); 282 | l.insertLast(4); 283 | 284 | l.forEach(node => { 285 | node.data += 10; 286 | }); 287 | 288 | expect(l.getAt(0).data).toEqual(11); 289 | expect(l.getAt(1).data).toEqual(12); 290 | expect(l.getAt(2).data).toEqual(13); 291 | expect(l.getAt(3).data).toEqual(14); 292 | }); 293 | }); 294 | 295 | describe('for...of loops', () => { 296 | test('works with the linked list', () => { 297 | const l = new List(); 298 | 299 | l.insertLast(1); 300 | l.insertLast(2); 301 | l.insertLast(3); 302 | l.insertLast(4); 303 | 304 | for (let node of l) { 305 | node.data += 10; 306 | } 307 | 308 | expect(l.getAt(0).data).toEqual(11); 309 | expect(l.getAt(1).data).toEqual(12); 310 | expect(l.getAt(2).data).toEqual(13); 311 | expect(l.getAt(3).data).toEqual(14); 312 | }); 313 | 314 | test('for...of works on an empty list', () => { 315 | const l = new List(); 316 | expect(() => { 317 | for (let node of l) { 318 | } 319 | }).not.toThrow(); 320 | }); 321 | }); 322 | -------------------------------------------------------------------------------- /completed_exercises/matrix/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts an integer N 3 | // and returns a NxN spiral matrix. 4 | // --- Examples 5 | // matrix(2) 6 | // [[undefined, undefined], 7 | // [undefined, undefined]] 8 | // matrix(3) 9 | // [[1, 2, 3], 10 | // [8, 9, 4], 11 | // [7, 6, 5]] 12 | // matrix(4) 13 | // [[1, 2, 3, 4], 14 | // [12, 13, 14, 5], 15 | // [11, 16, 15, 6], 16 | // [10, 9, 8, 7]] 17 | 18 | function matrix(n) { 19 | const results = []; 20 | 21 | for (let i = 0; i < n; i++) { 22 | results.push([]); 23 | } 24 | 25 | let counter = 1; 26 | let startColumn = 0; 27 | let endColumn = n - 1; 28 | let startRow = 0; 29 | let endRow = n - 1; 30 | while (startColumn <= endColumn && startRow <= endRow) { 31 | // Top row 32 | for (let i = startColumn; i <= endColumn; i++) { 33 | results[startRow][i] = counter; 34 | counter++; 35 | } 36 | startRow++; 37 | 38 | // Right column 39 | for (let i = startRow; i <= endRow; i++) { 40 | results[i][endColumn] = counter; 41 | counter++; 42 | } 43 | endColumn--; 44 | 45 | // Bottom row 46 | for (let i = endColumn; i >= startColumn; i--) { 47 | results[endRow][i] = counter; 48 | counter++; 49 | } 50 | endRow--; 51 | 52 | // start column 53 | for (let i = endRow; i >= startRow; i--) { 54 | results[i][startColumn] = counter; 55 | counter++; 56 | } 57 | startColumn++; 58 | } 59 | 60 | return results; 61 | } 62 | 63 | module.exports = matrix; 64 | -------------------------------------------------------------------------------- /completed_exercises/matrix/test.js: -------------------------------------------------------------------------------- 1 | const matrix = require('./index'); 2 | 3 | test('matrix is a function', () => { 4 | expect(typeof matrix).toEqual('function'); 5 | }); 6 | 7 | test('matrix produces a 2x2 array', () => { 8 | const m = matrix(2); 9 | expect(m.length).toEqual(2); 10 | expect(m[0]).toEqual([1, 2]); 11 | expect(m[1]).toEqual([4, 3]); 12 | }); 13 | 14 | test('matrix produces a 3x3 array', () => { 15 | const m = matrix(3); 16 | expect(m.length).toEqual(3); 17 | expect(m[0]).toEqual([1, 2, 3]); 18 | expect(m[1]).toEqual([8, 9, 4]); 19 | expect(m[2]).toEqual([7, 6, 5]); 20 | }); 21 | 22 | test('matrix produces a 4x4 array', () => { 23 | const m = matrix(4); 24 | expect(m.length).toEqual(4); 25 | expect(m[0]).toEqual([1, 2, 3, 4]); 26 | expect(m[1]).toEqual([12, 13, 14, 5]); 27 | expect(m[2]).toEqual([11, 16, 15, 6]); 28 | expect(m[3]).toEqual([10, 9, 8, 7]); 29 | }); 30 | -------------------------------------------------------------------------------- /completed_exercises/maxchar/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return the character that is most 3 | // commonly used in the string. 4 | // --- Examples 5 | // maxChar("abcccccccd") === "c" 6 | // maxChar("apple 1231111") === "1" 7 | 8 | function maxChar(str) { 9 | const charMap = {}; 10 | let max = 0; 11 | let maxChar = ''; 12 | 13 | for (let char of str) { 14 | if (charMap[char]) { 15 | charMap[char]++; 16 | } else { 17 | charMap[char] = 1; 18 | } 19 | } 20 | 21 | for (let char in charMap) { 22 | if (charMap[char] > max) { 23 | max = charMap[char]; 24 | maxChar = char; 25 | } 26 | } 27 | 28 | return maxChar; 29 | } 30 | 31 | module.exports = maxChar; 32 | -------------------------------------------------------------------------------- /completed_exercises/maxchar/test.js: -------------------------------------------------------------------------------- 1 | const maxChar = require('./index'); 2 | 3 | test('maxChar function exists', () => { 4 | expect(typeof maxChar).toEqual('function'); 5 | }); 6 | 7 | test('Finds the most frequently used char', () => { 8 | expect(maxChar('a')).toEqual('a'); 9 | expect(maxChar('abcdefghijklmnaaaaa')).toEqual('a'); 10 | }); 11 | 12 | test('Works with numbers in the string', () => { 13 | expect(maxChar('ab1c1d1e1f1g1')).toEqual('1'); 14 | }); 15 | -------------------------------------------------------------------------------- /completed_exercises/midpoint/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Return the 'middle' node of a linked list. 3 | // If the list has an even number of elements, return 4 | // the node at the end of the first half of the list. 5 | // *Do not* use a counter variable, *do not* retrieve 6 | // the size of the list, and only iterate 7 | // through the list one time. 8 | // --- Example 9 | // const l = new LinkedList(); 10 | // l.insertLast('a') 11 | // l.insertLast('b') 12 | // l.insertLast('c') 13 | // midpoint(l); // returns { data: 'b' } 14 | 15 | function midpoint(list) { 16 | let slow = list.getFirst(); 17 | let fast = list.getFirst(); 18 | 19 | while (fast.next && fast.next.next) { 20 | slow = slow.next; 21 | fast = fast.next.next; 22 | } 23 | 24 | return slow; 25 | } 26 | 27 | module.exports = midpoint; 28 | -------------------------------------------------------------------------------- /completed_exercises/midpoint/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor(values = []) { 10 | this.head = null; 11 | 12 | for (let value of values) { 13 | this.insertLast(value); 14 | } 15 | } 16 | 17 | clear() { 18 | this.head = null; 19 | } 20 | 21 | size() { 22 | let counter = 0; 23 | let node = this.head; 24 | 25 | while (node) { 26 | counter++; 27 | node = node.next; 28 | } 29 | 30 | return counter; 31 | } 32 | 33 | getAt(index) { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let counter = 0; 39 | let node = this.head; 40 | while (node) { 41 | if (counter === index) { 42 | return node; 43 | } 44 | node = node.next; 45 | counter++; 46 | } 47 | return null; 48 | } 49 | 50 | insertAt(data, index) { 51 | if (!this.head) { 52 | this.head = new Node(data); 53 | return; 54 | } 55 | 56 | if (index === 0) { 57 | this.head = new Node(data, this.head); 58 | return; 59 | } 60 | 61 | let counter = 1; 62 | let previous = this.head; 63 | let node = this.head.next; 64 | while (node) { 65 | if (counter === index) { 66 | previous.next = new Node(data, node); 67 | return; 68 | } 69 | previous = node; 70 | node = node.next; 71 | counter++; 72 | } 73 | 74 | previous.next = new Node(data, node); 75 | } 76 | 77 | removeFirst() { 78 | if (!this.head) { 79 | return; 80 | } 81 | 82 | this.head = this.head.next; 83 | } 84 | 85 | removeLast() { 86 | if (!this.head) { 87 | return; 88 | } 89 | 90 | if (!this.head.next) { 91 | this.head = null; 92 | return; 93 | } 94 | 95 | let previous = this.head; 96 | let node = this.head.next; 97 | while (node.next) { 98 | previous = node; 99 | node = node.next; 100 | } 101 | previous.next = null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | let counter = 0; 110 | let node = this.head; 111 | while (node) { 112 | if (counter === index - 1) { 113 | if (node.next) { 114 | return (node.next = node.next.next); 115 | } else { 116 | return (node.next = null); 117 | } 118 | } 119 | node = node.next; 120 | counter++; 121 | } 122 | } 123 | 124 | getFirst() { 125 | return this.head; 126 | } 127 | 128 | insertFirst(data) { 129 | this.head = new Node(data, this.getFirst()); 130 | } 131 | 132 | getLast() { 133 | if (!this.head) { 134 | return null; 135 | } 136 | 137 | let node = this.head; 138 | while (node.next) { 139 | node = node.next; 140 | } 141 | 142 | return node; 143 | } 144 | 145 | insertLast(data) { 146 | const last = this.getLast(); 147 | 148 | if (last) { 149 | last.next = new Node(data); 150 | return last.next; 151 | } else { 152 | this.head = new Node(data); 153 | return this.head; 154 | } 155 | } 156 | 157 | forEach(fn) { 158 | if (!this.head) { 159 | return null; 160 | } 161 | 162 | let node = this.head; 163 | while (node) { 164 | fn(node); 165 | node = node.next; 166 | } 167 | } 168 | 169 | *[Symbol.iterator]() { 170 | let node = this.head; 171 | while (node) { 172 | yield node; 173 | node = node.next; 174 | } 175 | } 176 | } 177 | 178 | module.exports = { Node, LinkedList }; 179 | -------------------------------------------------------------------------------- /completed_exercises/midpoint/test.js: -------------------------------------------------------------------------------- 1 | const midpoint = require('./index'); 2 | const L = require('./linkedlist'); 3 | const Node = L.Node; 4 | const LinkedList = L.LinkedList; 5 | 6 | test('Midpoint is a function', () => { 7 | expect(typeof midpoint).toEqual('function'); 8 | }); 9 | 10 | describe('Midpoint returns the middle node of an odd numbered list', () => { 11 | test('when the list has 3 elements', () => { 12 | const l = new LinkedList(); 13 | l.insertLast('a'); 14 | l.insertLast('b'); 15 | l.insertLast('c'); 16 | expect(midpoint(l).data).toEqual('b'); 17 | }); 18 | 19 | test('when the list has 5 elements', () => { 20 | const l = new LinkedList(); 21 | l.insertLast('a'); 22 | l.insertLast('b'); 23 | l.insertLast('c'); 24 | l.insertLast('d'); 25 | l.insertLast('e'); 26 | expect(midpoint(l).data).toEqual('c'); 27 | }); 28 | }); 29 | 30 | describe('Midpoint returns the middle node of an even numbered list', () => { 31 | test('when the list has 2 elements', () => { 32 | const l = new LinkedList(); 33 | l.insertLast('a'); 34 | l.insertLast('b'); 35 | expect(midpoint(l).data).toEqual('a'); 36 | }); 37 | 38 | test('when the list has 4 elements', () => { 39 | const l = new LinkedList(); 40 | l.insertLast('a'); 41 | l.insertLast('b'); 42 | l.insertLast('c'); 43 | l.insertLast('d'); 44 | expect(midpoint(l).data).toEqual('b'); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /completed_exercises/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "author": "", 10 | "license": "ISC" 11 | } 12 | -------------------------------------------------------------------------------- /completed_exercises/palindrome/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return true if the string is a palindrome 3 | // or false if it is not. Palindromes are strings that 4 | // form the same word if it is reversed. *Do* include spaces 5 | // and punctuation in determining if the string is a palindrome. 6 | // --- Examples: 7 | // palindrome("abba") === true 8 | // palindrome("abcdefg") === false 9 | 10 | function palindrome(str) { 11 | return str.split('').every((char, i) => { 12 | return char === str[str.length - i - 1]; 13 | }); 14 | } 15 | 16 | module.exports = palindrome; 17 | 18 | // function palindrome(str) { 19 | // const reversed = str 20 | // .split('') 21 | // .reverse() 22 | // .join(''); 23 | // 24 | // return str === reversed; 25 | // } 26 | -------------------------------------------------------------------------------- /completed_exercises/palindrome/test.js: -------------------------------------------------------------------------------- 1 | const palindrome = require('./index'); 2 | 3 | test('palindrome function is defined', () => { 4 | expect(typeof palindrome).toEqual('function'); 5 | }); 6 | 7 | test('"aba" is a palindrome', () => { 8 | expect(palindrome('aba')).toBeTruthy(); 9 | }); 10 | 11 | test('" aba" is not a palindrome', () => { 12 | expect(palindrome(' aba')).toBeFalsy(); 13 | }); 14 | 15 | test('"aba " is not a palindrome', () => { 16 | expect(palindrome('aba ')).toBeFalsy(); 17 | }); 18 | 19 | test('"greetings" is not a palindrome', () => { 20 | expect(palindrome('greetings')).toBeFalsy(); 21 | }); 22 | 23 | test('"1000000001" a palindrome', () => { 24 | expect(palindrome('1000000001')).toBeTruthy(); 25 | }); 26 | 27 | test('"Fish hsif" is not a palindrome', () => { 28 | expect(palindrome('Fish hsif')).toBeFalsy(); 29 | }); 30 | 31 | test('"pennep" a palindrome', () => { 32 | expect(palindrome('pennep')).toBeTruthy(); 33 | }); 34 | -------------------------------------------------------------------------------- /completed_exercises/pyramid/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a positive number N. 3 | // The function should console log a pyramid shape 4 | // with N levels using the # character. Make sure the 5 | // pyramid has spaces on both the left *and* right hand sides 6 | // --- Examples 7 | // pyramid(1) 8 | // '#' 9 | // pyramid(2) 10 | // ' # ' 11 | // '###' 12 | // pyramid(3) 13 | // ' # ' 14 | // ' ### ' 15 | // '#####' 16 | 17 | function pyramid(n, row = 0, level = '') { 18 | if (row === n) { 19 | return; 20 | } 21 | 22 | if (level.length === 2 * n - 1) { 23 | console.log(level); 24 | return pyramid(n, row + 1); 25 | } 26 | 27 | const midpoint = Math.floor((2 * n - 1) / 2); 28 | let add; 29 | if (midpoint - row <= level.length && midpoint + row >= level.length) { 30 | add = '#'; 31 | } else { 32 | add = ' '; 33 | } 34 | pyramid(n, row, level + add); 35 | } 36 | 37 | module.exports = pyramid; 38 | // 39 | // function pyramid(n) { 40 | // const midpoint = Math.floor((2 * n - 1) / 2); 41 | // 42 | // for (let row = 0; row < n; row++) { 43 | // let level = ''; 44 | // 45 | // for (let column = 0; column < 2 * n - 1; column++) { 46 | // if (midpoint - row <= column && midpoint + row >= column) { 47 | // level += '#'; 48 | // } else { 49 | // level += ' '; 50 | // } 51 | // } 52 | // 53 | // console.log(level); 54 | // } 55 | // } 56 | -------------------------------------------------------------------------------- /completed_exercises/pyramid/test.js: -------------------------------------------------------------------------------- 1 | const pyramid = require('./index'); 2 | 3 | beforeEach(() => { 4 | jest.spyOn(console, 'log'); 5 | }); 6 | 7 | afterEach(() => { 8 | console.log.mockRestore(); 9 | }); 10 | 11 | test('pyramid is a function', () => { 12 | expect(typeof pyramid).toEqual('function'); 13 | }); 14 | 15 | test('prints a pryamid for n = 2', () => { 16 | pyramid(2); 17 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 18 | expect(console.log.mock.calls[1][0]).toEqual('###'); 19 | expect(console.log.mock.calls.length).toEqual(2); 20 | }); 21 | 22 | test('prints a pryamid for n = 3', () => { 23 | pyramid(3); 24 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 25 | expect(console.log.mock.calls[1][0]).toEqual(' ### '); 26 | expect(console.log.mock.calls[2][0]).toEqual('#####'); 27 | expect(console.log.mock.calls.length).toEqual(3); 28 | }); 29 | 30 | test('prints a pryamid for n = 4', () => { 31 | pyramid(4); 32 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 33 | expect(console.log.mock.calls[1][0]).toEqual(' ### '); 34 | expect(console.log.mock.calls[2][0]).toEqual(' ##### '); 35 | expect(console.log.mock.calls[3][0]).toEqual('#######'); 36 | expect(console.log.mock.calls.length).toEqual(4); 37 | }); 38 | -------------------------------------------------------------------------------- /completed_exercises/qfroms/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement a Queue datastructure using two stacks. 3 | // *Do not* create an array inside of the 'Queue' class. 4 | // Queue should implement the methods 'add', 'remove', and 'peek'. 5 | // For a reminder on what each method does, look back 6 | // at the Queue exercise. 7 | // --- Examples 8 | // const q = new Queue(); 9 | // q.add(1); 10 | // q.add(2); 11 | // q.peek(); // returns 1 12 | // q.remove(); // returns 1 13 | // q.remove(); // returns 2 14 | 15 | const Stack = require('./stack'); 16 | 17 | class Queue { 18 | constructor() { 19 | this.first = new Stack(); 20 | this.second = new Stack(); 21 | } 22 | 23 | add(record) { 24 | this.first.push(record); 25 | } 26 | 27 | remove() { 28 | while (this.first.peek()) { 29 | this.second.push(this.first.pop()); 30 | } 31 | 32 | const record = this.second.pop(); 33 | 34 | while (this.second.peek()) { 35 | this.first.push(this.second.pop()); 36 | } 37 | 38 | return record; 39 | } 40 | 41 | peek() { 42 | while (this.first.peek()) { 43 | this.second.push(this.first.pop()); 44 | } 45 | 46 | const record = this.second.peek(); 47 | 48 | while (this.second.peek()) { 49 | this.first.push(this.second.pop()); 50 | } 51 | 52 | return record; 53 | } 54 | } 55 | 56 | module.exports = Queue; 57 | -------------------------------------------------------------------------------- /completed_exercises/qfroms/stack.js: -------------------------------------------------------------------------------- 1 | class Stack { 2 | constructor() { 3 | this.data = []; 4 | } 5 | 6 | push(record) { 7 | this.data.push(record); 8 | } 9 | 10 | pop() { 11 | return this.data.pop(); 12 | } 13 | 14 | peek() { 15 | return this.data[this.data.length - 1]; 16 | } 17 | } 18 | 19 | module.exports = Stack; 20 | -------------------------------------------------------------------------------- /completed_exercises/qfroms/test.js: -------------------------------------------------------------------------------- 1 | const Queue = require('./index'); 2 | 3 | test('Queue is a class', () => { 4 | expect(typeof Queue.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('can add elements to a queue', () => { 8 | const q = new Queue(); 9 | expect(() => { 10 | q.add(1); 11 | }).not.toThrow(); 12 | }); 13 | 14 | test('can remove elements from a queue', () => { 15 | const q = new Queue(); 16 | expect(() => { 17 | q.add(1); 18 | q.remove(); 19 | }).not.toThrow(); 20 | }); 21 | 22 | test('Order of elements is maintained', () => { 23 | const q = new Queue(); 24 | q.add(1); 25 | q.add(2); 26 | q.add(3); 27 | expect(q.remove()).toEqual(1); 28 | expect(q.remove()).toEqual(2); 29 | expect(q.remove()).toEqual(3); 30 | expect(q.remove()).toEqual(undefined); 31 | }); 32 | 33 | test('peek returns, but does not remove, the first value', () => { 34 | const q = new Queue(); 35 | q.add(1); 36 | q.add(2); 37 | expect(q.peek()).toEqual(1); 38 | expect(q.peek()).toEqual(1); 39 | expect(q.remove()).toEqual(1); 40 | expect(q.remove()).toEqual(2); 41 | }); 42 | -------------------------------------------------------------------------------- /completed_exercises/queue/index.js: -------------------------------------------------------------------------------- 1 | // --- Description 2 | // Create a queue data structure. The queue 3 | // should be a class with methods 'add' and 'remove'. 4 | // Adding to the queue should store an element until 5 | // it is removed 6 | // --- Examples 7 | // const q = new Queue(); 8 | // q.add(1); 9 | // q.remove(); // returns 1; 10 | 11 | class Queue { 12 | constructor() { 13 | this.data = []; 14 | } 15 | 16 | add(record) { 17 | this.data.unshift(record); 18 | } 19 | 20 | remove() { 21 | return this.data.pop(); 22 | } 23 | } 24 | 25 | module.exports = Queue; 26 | -------------------------------------------------------------------------------- /completed_exercises/queue/test.js: -------------------------------------------------------------------------------- 1 | const Queue = require('./index'); 2 | 3 | test('Queue is a class', () => { 4 | expect(typeof Queue.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('can add elements to a queue', () => { 8 | const q = new Queue(); 9 | expect(() => { 10 | q.add(1); 11 | }).not.toThrow(); 12 | }); 13 | 14 | test('can remove elements from a queue', () => { 15 | const q = new Queue(); 16 | expect(() => { 17 | q.add(1); 18 | q.remove(); 19 | }).not.toThrow(); 20 | }); 21 | 22 | test('Order of elements is maintained', () => { 23 | const q = new Queue(); 24 | q.add(1); 25 | q.add(2); 26 | q.add(3); 27 | expect(q.remove()).toEqual(1); 28 | expect(q.remove()).toEqual(2); 29 | expect(q.remove()).toEqual(3); 30 | expect(q.remove()).toEqual(undefined); 31 | }); 32 | -------------------------------------------------------------------------------- /completed_exercises/reverseint/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given an integer, return an integer that is the reverse 3 | // ordering of numbers. 4 | // --- Examples 5 | // reverseInt(15) === 51 6 | // reverseInt(981) === 189 7 | // reverseInt(500) === 5 8 | // reverseInt(-15) === -51 9 | // reverseInt(-90) === -9 10 | 11 | function reverseInt(n) { 12 | const reversed = n 13 | .toString() 14 | .split('') 15 | .reverse() 16 | .join(''); 17 | 18 | return parseInt(reversed) * Math.sign(n); 19 | } 20 | 21 | module.exports = reverseInt; 22 | -------------------------------------------------------------------------------- /completed_exercises/reverseint/test.js: -------------------------------------------------------------------------------- 1 | const reverseInt = require('./index'); 2 | 3 | test('ReverseInt function exists', () => { 4 | expect(reverseInt).toBeDefined(); 5 | }); 6 | 7 | test('ReverseInt handles 0 as an input', () => { 8 | expect(reverseInt(0)).toEqual(0); 9 | }); 10 | 11 | test('ReverseInt flips a positive number', () => { 12 | expect(reverseInt(5)).toEqual(5); 13 | expect(reverseInt(15)).toEqual(51); 14 | expect(reverseInt(90)).toEqual(9); 15 | expect(reverseInt(2359)).toEqual(9532); 16 | }); 17 | 18 | test('ReverseInt flips a negative number', () => { 19 | expect(reverseInt(-5)).toEqual(-5); 20 | expect(reverseInt(-15)).toEqual(-51); 21 | expect(reverseInt(-90)).toEqual(-9); 22 | expect(reverseInt(-2359)).toEqual(-9532); 23 | }); 24 | -------------------------------------------------------------------------------- /completed_exercises/reversestring/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return a new string with the reversed 3 | // order of characters 4 | // --- Examples 5 | // reverse('apple') === 'leppa' 6 | // reverse('hello') === 'olleh' 7 | // reverse('Greetings!') === '!sgniteerG' 8 | 9 | function reverse(str) { 10 | return str.split('').reduce((rev, char) => char + rev, ''); 11 | } 12 | 13 | module.exports = reverse; 14 | 15 | // function reverse(str) { 16 | // return str 17 | // .split('') 18 | // .reverse() 19 | // .join(''); 20 | // } 21 | 22 | // function reverse(str) { 23 | // let reversed = ''; 24 | // 25 | // for (let character of str) { 26 | // reversed = character + reversed; 27 | // } 28 | // 29 | // return reversed; 30 | // } 31 | -------------------------------------------------------------------------------- /completed_exercises/reversestring/test.js: -------------------------------------------------------------------------------- 1 | const reverse = require('./index'); 2 | 3 | test('Reverse function exists', () => { 4 | expect(reverse).toBeDefined(); 5 | }); 6 | 7 | test('Reverse reverses a string', () => { 8 | expect(reverse('abcd')).toEqual('dcba'); 9 | }); 10 | 11 | test('Reverse reverses a string', () => { 12 | expect(reverse(' abcd')).toEqual('dcba '); 13 | }); 14 | -------------------------------------------------------------------------------- /completed_exercises/sorting/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement bubbleSort, selectionSort, and mergeSort 3 | 4 | function bubbleSort(arr) { 5 | // Implement bubblesort 6 | for (let i = 0; i < arr.length; i++) { 7 | for (let j = 0; j < (arr.length - i - 1); j++) { 8 | if (arr[j] > arr[j+1]) { 9 | const lesser = arr[j+1]; 10 | arr[j+1] = arr[j]; 11 | arr[j] = lesser; 12 | } 13 | } 14 | } 15 | 16 | // return the sorted array 17 | return arr; 18 | } 19 | 20 | function selectionSort(arr) { 21 | for (let i = 0; i < arr.length; i++) { 22 | let indexOfMin = i; 23 | 24 | for (let j = i+1; j { 16 | test('sorts an array', () => { 17 | expect(bubbleSort(getArray())).toEqual(getSortedArray()); 18 | }); 19 | }); 20 | 21 | describe('Selection sort', () => { 22 | test('sorts an array', () => { 23 | expect(selectionSort(getArray())).toEqual(getSortedArray()); 24 | }); 25 | }); 26 | 27 | describe('Merge sort', () => { 28 | test('merge function can join together two sorted arrays', () => { 29 | const left = [1, 10]; 30 | const right = [2, 8, 12]; 31 | 32 | expect(merge(left, right)).toEqual([1,2,8,10,12]); 33 | }); 34 | 35 | test('sorts an array', () => { 36 | expect(mergeSort(getArray())).toEqual(getSortedArray()); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /completed_exercises/stack/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Create a stack data structure. The stack 3 | // should be a class with methods 'push', 'pop', and 4 | // 'peek'. Adding an element to the stack should 5 | // store it until it is removed. 6 | // --- Examples 7 | // const s = new Stack(); 8 | // s.push(1); 9 | // s.push(2); 10 | // s.pop(); // returns 2 11 | // s.pop(); // returns 1 12 | 13 | class Stack { 14 | constructor() { 15 | this.data = []; 16 | } 17 | 18 | push(record) { 19 | this.data.push(record); 20 | } 21 | 22 | pop() { 23 | return this.data.pop(); 24 | } 25 | 26 | peek() { 27 | return this.data[this.data.length - 1]; 28 | } 29 | } 30 | 31 | module.exports = Stack; 32 | -------------------------------------------------------------------------------- /completed_exercises/stack/test.js: -------------------------------------------------------------------------------- 1 | const Stack = require('./index'); 2 | 3 | test('Stack is a class', () => { 4 | expect(typeof Stack.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('stack can add and remove items', () => { 8 | const s = new Stack(); 9 | s.push(1); 10 | expect(s.pop()).toEqual(1); 11 | s.push(2); 12 | expect(s.pop()).toEqual(2); 13 | }); 14 | 15 | test('stack can follows first in, last out', () => { 16 | const s = new Stack(); 17 | s.push(1); 18 | s.push(2); 19 | s.push(3); 20 | expect(s.pop()).toEqual(3); 21 | expect(s.pop()).toEqual(2); 22 | expect(s.pop()).toEqual(1); 23 | }); 24 | 25 | test('peek returns the first element but doesnt pop it', () => { 26 | const s = new Stack(); 27 | s.push(1); 28 | s.push(2); 29 | s.push(3); 30 | expect(s.peek()).toEqual(3); 31 | expect(s.pop()).toEqual(3); 32 | expect(s.peek()).toEqual(2); 33 | expect(s.pop()).toEqual(2); 34 | expect(s.peek()).toEqual(1); 35 | expect(s.pop()).toEqual(1); 36 | }); 37 | -------------------------------------------------------------------------------- /completed_exercises/steps/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a positive number N. 3 | // The function should console log a step shape 4 | // with N levels using the # character. Make sure the 5 | // step has spaces on the right hand side! 6 | // --- Examples 7 | // steps(2) 8 | // '# ' 9 | // '##' 10 | // steps(3) 11 | // '# ' 12 | // '## ' 13 | // '###' 14 | // steps(4) 15 | // '# ' 16 | // '## ' 17 | // '### ' 18 | // '####' 19 | 20 | function steps(n, row = 0, stair = '') { 21 | if (n === row) { 22 | return; 23 | } 24 | 25 | if (n === stair.length) { 26 | console.log(stair); 27 | return steps(n, row + 1); 28 | } 29 | 30 | const add = stair.length <= row ? '#' : ' '; 31 | steps(n, row, stair + add); 32 | } 33 | 34 | module.exports = steps; 35 | 36 | // function steps(n) { 37 | // for (let row = 0; row < n; row++) { 38 | // let stair = ''; 39 | // 40 | // for (let column = 0; column < n; column++) { 41 | // if (column <= row) { 42 | // stair += '#'; 43 | // } else { 44 | // stair += ' '; 45 | // } 46 | // } 47 | // 48 | // console.log(stair); 49 | // } 50 | // } 51 | -------------------------------------------------------------------------------- /completed_exercises/steps/test.js: -------------------------------------------------------------------------------- 1 | const steps = require('./index'); 2 | 3 | beforeEach(() => { 4 | jest.spyOn(console, 'log'); 5 | }); 6 | 7 | afterEach(() => { 8 | console.log.mockRestore(); 9 | }); 10 | 11 | test('steps is a function', () => { 12 | expect(typeof steps).toEqual('function'); 13 | }); 14 | 15 | test('steps called with n = 1', () => { 16 | steps(1); 17 | expect(console.log.mock.calls[0][0]).toEqual('#'); 18 | expect(console.log.mock.calls.length).toEqual(1); 19 | }); 20 | 21 | test('steps called with n = 2', () => { 22 | steps(2); 23 | expect(console.log.mock.calls[0][0]).toEqual('# '); 24 | expect(console.log.mock.calls[1][0]).toEqual('##'); 25 | expect(console.log.mock.calls.length).toEqual(2); 26 | }); 27 | 28 | test('steps called with n = 3', () => { 29 | steps(3); 30 | expect(console.log.mock.calls[0][0]).toEqual('# '); 31 | expect(console.log.mock.calls[1][0]).toEqual('## '); 32 | expect(console.log.mock.calls[2][0]).toEqual('###'); 33 | expect(console.log.mock.calls.length).toEqual(3); 34 | }); 35 | -------------------------------------------------------------------------------- /completed_exercises/tree/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Create a node class. The constructor 3 | // should accept an argument that gets assigned 4 | // to the data property and initialize an 5 | // empty array for storing children. The node 6 | // class should have methods 'add' and 'remove'. 7 | // 2) Create a tree class. The tree constructor 8 | // should initialize a 'root' property to null. 9 | // 3) Implement 'traverseBF' and 'traverseDF' 10 | // on the tree class. Each method should accept a 11 | // function that gets called with each element in the tree 12 | 13 | class Node { 14 | constructor(data) { 15 | this.data = data; 16 | this.children = []; 17 | } 18 | 19 | add(data) { 20 | this.children.push(new Node(data)); 21 | } 22 | 23 | remove(data) { 24 | this.children = this.children.filter(node => { 25 | return node.data !== data; 26 | }); 27 | } 28 | } 29 | 30 | class Tree { 31 | constructor() { 32 | this.root = null; 33 | } 34 | 35 | traverseBF(fn) { 36 | const arr = [this.root]; 37 | while (arr.length) { 38 | const node = arr.shift(); 39 | 40 | arr.push(...node.children); 41 | fn(node); 42 | } 43 | } 44 | 45 | traverseDF(fn) { 46 | const arr = [this.root]; 47 | while (arr.length) { 48 | const node = arr.shift(); 49 | 50 | arr.unshift(...node.children); 51 | fn(node); 52 | } 53 | } 54 | } 55 | 56 | module.exports = { Tree, Node }; 57 | -------------------------------------------------------------------------------- /completed_exercises/tree/test.js: -------------------------------------------------------------------------------- 1 | const T = require('./index'); 2 | const Node = T.Node; 3 | const Tree = T.Tree; 4 | 5 | describe('Node', () => { 6 | test('Node is a constructor', () => { 7 | expect(typeof Node.prototype.constructor).toEqual('function'); 8 | }); 9 | 10 | test('Node has a data and children properties', () => { 11 | const n = new Node('a'); 12 | expect(n.data).toEqual('a'); 13 | expect(n.children.length).toEqual(0); 14 | }); 15 | 16 | test('Node can add children', () => { 17 | const n = new Node('a'); 18 | n.add('b'); 19 | expect(n.children.length).toEqual(1); 20 | expect(n.children[0].children).toEqual([]); 21 | }); 22 | 23 | test('Node can remove children', () => { 24 | const n = new Node('a'); 25 | n.add('b'); 26 | expect(n.children.length).toEqual(1); 27 | n.remove('b'); 28 | expect(n.children.length).toEqual(0); 29 | }); 30 | }); 31 | 32 | describe('Tree', () => { 33 | test('starts empty', () => { 34 | const t = new Tree(); 35 | expect(t.root).toEqual(null); 36 | }); 37 | 38 | test('Can traverse bf', () => { 39 | const letters = []; 40 | const t = new Tree(); 41 | t.root = new Node('a'); 42 | t.root.add('b'); 43 | t.root.add('c'); 44 | t.root.children[0].add('d'); 45 | 46 | t.traverseBF(node => { 47 | letters.push(node.data); 48 | }); 49 | 50 | expect(letters).toEqual(['a', 'b', 'c', 'd']); 51 | }); 52 | 53 | test('Can traverse DF', () => { 54 | const letters = []; 55 | const t = new Tree(); 56 | t.root = new Node('a'); 57 | t.root.add('b'); 58 | t.root.add('d'); 59 | t.root.children[0].add('c'); 60 | 61 | t.traverseDF(node => { 62 | letters.push(node.data); 63 | }); 64 | 65 | expect(letters).toEqual(['a', 'b', 'c', 'd']); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /completed_exercises/validate/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a node, validate the binary search tree, 3 | // ensuring that every node's left hand child is 4 | // less than the parent node's value, and that 5 | // every node's right hand child is greater than 6 | // the parent 7 | 8 | function validate(node, min = null, max = null) { 9 | if (max !== null && node.data > max) { 10 | return false; 11 | } 12 | 13 | if (min !== null && node.data < min) { 14 | return false; 15 | } 16 | 17 | if (node.left && !validate(node.left, min, node.data)) { 18 | return false; 19 | } 20 | 21 | if (node.right && !validate(node.right, node.data, max)) { 22 | return false; 23 | } 24 | 25 | return true; 26 | } 27 | 28 | module.exports = validate; 29 | -------------------------------------------------------------------------------- /completed_exercises/validate/node.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | 8 | insert(data) { 9 | if (data < this.data && this.left) { 10 | this.left.insert(data); 11 | } else if (data < this.data) { 12 | this.left = new Node(data); 13 | } else if (data > this.data && this.right) { 14 | this.right.insert(data); 15 | } else if (data > this.data) { 16 | this.right = new Node(data); 17 | } 18 | } 19 | } 20 | 21 | module.exports = Node; 22 | -------------------------------------------------------------------------------- /completed_exercises/validate/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./node'); 2 | const validate = require('./index'); 3 | 4 | test('Validate recognizes a valid BST', () => { 5 | const n = new Node(10); 6 | n.insert(5); 7 | n.insert(15); 8 | n.insert(0); 9 | n.insert(20); 10 | 11 | expect(validate(n)).toEqual(true); 12 | }); 13 | 14 | test('Validate recognizes an invalid BST', () => { 15 | const n = new Node(10); 16 | n.insert(5); 17 | n.insert(15); 18 | n.insert(0); 19 | n.insert(20); 20 | n.left.left.right = new Node(999); 21 | 22 | expect(validate(n)).toEqual(false); 23 | }); 24 | -------------------------------------------------------------------------------- /completed_exercises/vowels/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that returns the number of vowels 3 | // used in a string. Vowels are the characters 'a', 'e' 4 | // 'i', 'o', and 'u'. 5 | // --- Examples 6 | // vowels('Hi There!') --> 3 7 | // vowels('Why do you ask?') --> 4 8 | // vowels('Why?') --> 0 9 | 10 | function vowels(str) { 11 | const matches = str.match(/[aeiou]/gi); 12 | return matches ? matches.length : 0; 13 | } 14 | 15 | module.exports = vowels; 16 | 17 | // function vowels(str) { 18 | // let count = 0; 19 | // const checker = ['a', 'e', 'i', 'o', 'u']; 20 | // 21 | // for (let char of str.toLowerCase()) { 22 | // if (checker.includes(char)) { 23 | // count++; 24 | // } 25 | // } 26 | // 27 | // return count; 28 | // } 29 | -------------------------------------------------------------------------------- /completed_exercises/vowels/test.js: -------------------------------------------------------------------------------- 1 | const vowels = require('./index'); 2 | 3 | test('Vowels is a function', () => { 4 | expect(typeof vowels).toEqual('function'); 5 | }); 6 | 7 | test('returns the number of vowels used', () => { 8 | expect(vowels('aeiou')).toEqual(5); 9 | }); 10 | 11 | test('returns the number of vowels used', () => { 12 | expect(vowels('abcdefghijklmnopqrstuvwxyz')).toEqual(5); 13 | }); 14 | 15 | test('returns the number of vowels used', () => { 16 | expect(vowels('bcdfghjkl')).toEqual(0); 17 | }); 18 | -------------------------------------------------------------------------------- /completed_exercises/weave/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Complete the task in weave/queue.js 3 | // 2) Implement the 'weave' function. Weave 4 | // receives two queues as arguments and combines the 5 | // contents of each into a new, third queue. 6 | // The third queue should contain the *alterating* content 7 | // of the two queues. The function should handle 8 | // queues of different lengths without inserting 9 | // 'undefined' into the new one. 10 | // *Do not* access the array inside of any queue, only 11 | // use the 'add', 'remove', and 'peek' functions. 12 | // --- Example 13 | // const queueOne = new Queue(); 14 | // queueOne.add(1); 15 | // queueOne.add(2); 16 | // const queueTwo = new Queue(); 17 | // queueTwo.add('Hi'); 18 | // queueTwo.add('There'); 19 | // const q = weave(queueOne, queueTwo); 20 | // q.remove() // 1 21 | // q.remove() // 'Hi' 22 | // q.remove() // 2 23 | // q.remove() // 'There' 24 | 25 | const Queue = require('./queue'); 26 | 27 | function weave(sourceOne, sourceTwo) { 28 | const q = new Queue(); 29 | 30 | while (sourceOne.peek() || sourceTwo.peek()) { 31 | if (sourceOne.peek()) { 32 | q.add(sourceOne.remove()); 33 | } 34 | 35 | if (sourceTwo.peek()) { 36 | q.add(sourceTwo.remove()); 37 | } 38 | } 39 | 40 | return q; 41 | } 42 | 43 | module.exports = weave; 44 | -------------------------------------------------------------------------------- /completed_exercises/weave/queue.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement a 'peek' method in this Queue class. 3 | // Peek should return the last element (the next 4 | // one to be returned) from the queue *without* 5 | // removing it. 6 | 7 | class Queue { 8 | constructor() { 9 | this.data = []; 10 | } 11 | 12 | add(record) { 13 | this.data.unshift(record); 14 | } 15 | 16 | remove() { 17 | return this.data.pop(); 18 | } 19 | 20 | peek() { 21 | return this.data[this.data.length - 1]; 22 | } 23 | } 24 | 25 | module.exports = Queue; 26 | -------------------------------------------------------------------------------- /completed_exercises/weave/test.js: -------------------------------------------------------------------------------- 1 | const weave = require('./index'); 2 | const Queue = require('./queue'); 3 | 4 | test('queues have a peek function', () => { 5 | const q = new Queue(); 6 | expect(typeof q.peek).toEqual('function'); 7 | }); 8 | 9 | test('peek returns, but does not remove, the first value', () => { 10 | const q = new Queue(); 11 | q.add(1); 12 | q.add(2); 13 | expect(q.peek()).toEqual(1); 14 | expect(q.peek()).toEqual(1); 15 | expect(q.remove()).toEqual(1); 16 | expect(q.remove()).toEqual(2); 17 | }); 18 | 19 | test('weave is a function', () => { 20 | expect(typeof weave).toEqual('function'); 21 | }); 22 | 23 | test('weave can combine two queues', () => { 24 | const one = new Queue(); 25 | one.add(1); 26 | one.add(2); 27 | one.add(3); 28 | one.add(4); 29 | const two = new Queue(); 30 | two.add('one'); 31 | two.add('two'); 32 | two.add('three'); 33 | two.add('four'); 34 | 35 | const result = weave(one, two); 36 | expect(result.remove()).toEqual(1); 37 | expect(result.remove()).toEqual('one'); 38 | expect(result.remove()).toEqual(2); 39 | expect(result.remove()).toEqual('two'); 40 | expect(result.remove()).toEqual(3); 41 | expect(result.remove()).toEqual('three'); 42 | expect(result.remove()).toEqual(4); 43 | expect(result.remove()).toEqual('four'); 44 | expect(result.remove()).toBeUndefined(); 45 | }); 46 | -------------------------------------------------------------------------------- /diagrams/01/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/01/.gitkeep -------------------------------------------------------------------------------- /diagrams/01/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/02/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/02/.gitkeep -------------------------------------------------------------------------------- /diagrams/02/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/03/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/03/.gitkeep -------------------------------------------------------------------------------- /diagrams/04/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/04/.gitkeep -------------------------------------------------------------------------------- /diagrams/05/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/05/.gitkeep -------------------------------------------------------------------------------- /diagrams/06/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/06/.gitkeep -------------------------------------------------------------------------------- /diagrams/07/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/07/.gitkeep -------------------------------------------------------------------------------- /diagrams/07/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/08/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/08/.gitkeep -------------------------------------------------------------------------------- /diagrams/09/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/09/.gitkeep -------------------------------------------------------------------------------- /diagrams/09/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /diagrams/10/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/StephenGrider/AlgoCasts/feeab87936c294d647721184753b164bbf9f46d6/diagrams/10/.gitkeep -------------------------------------------------------------------------------- /diagrams/10/diagrams.xml: -------------------------------------------------------------------------------- 1 | 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 -------------------------------------------------------------------------------- /exercises/anagrams/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Check to see if two provided strings are anagrams of eachother. 3 | // One string is an anagram of another if it uses the same characters 4 | // in the same quantity. Only consider characters, not spaces 5 | // or punctuation. Consider capital letters to be the same as lower case 6 | // --- Examples 7 | // anagrams('rail safety', 'fairy tales') --> True 8 | // anagrams('RAIL! SAFETY!', 'fairy tales') --> True 9 | // anagrams('Hi there', 'Bye there') --> False 10 | 11 | function anagrams(stringA, stringB) {} 12 | 13 | module.exports = anagrams; 14 | -------------------------------------------------------------------------------- /exercises/anagrams/test.js: -------------------------------------------------------------------------------- 1 | const anagrams = require('./index.js'); 2 | 3 | test('anagrams function exists', () => { 4 | expect(typeof anagrams).toEqual('function'); 5 | }); 6 | 7 | test('"hello" is an anagram of "llohe"', () => { 8 | expect(anagrams('hello', 'llohe')).toBeTruthy(); 9 | }); 10 | 11 | test('"Whoa! Hi!" is an anagram of "Hi! Whoa!"', () => { 12 | expect(anagrams('Whoa! Hi!', 'Hi! Whoa!')).toBeTruthy(); 13 | }); 14 | 15 | test('"One One" is not an anagram of "Two two two"', () => { 16 | expect(anagrams('One One', 'Two two two')).toBeFalsy(); 17 | }); 18 | 19 | test('"One one" is not an anagram of "One one c"', () => { 20 | expect(anagrams('One one', 'One one c')).toBeFalsy(); 21 | }); 22 | 23 | test('"A tree, a life, a bench" is not an anagram of "A tree, a fence, a yard"', () => { 24 | expect( 25 | anagrams('A tree, a life, a bench', 'A tree, a fence, a yard') 26 | ).toBeFalsy(); 27 | }); 28 | -------------------------------------------------------------------------------- /exercises/bst/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Implement the Node class to create 3 | // a binary search tree. The constructor 4 | // should initialize values 'data', 'left', 5 | // and 'right'. 6 | // 2) Implement the 'insert' method for the 7 | // Node class. Insert should accept an argument 8 | // 'data', then create an insert a new node 9 | // at the appropriate location in the tree. 10 | // 3) Implement the 'contains' method for the Node 11 | // class. Contains should accept a 'data' argument 12 | // and return the Node in the tree with the same value. 13 | 14 | class Node {} 15 | 16 | module.exports = Node; 17 | -------------------------------------------------------------------------------- /exercises/bst/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./index'); 2 | 3 | test('Node is a constructor', () => { 4 | expect(typeof Node.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('Node can insert correctly', () => { 8 | const node = new Node(10); 9 | node.insert(5); 10 | node.insert(15); 11 | node.insert(17); 12 | 13 | expect(node.left.data).toEqual(5); 14 | expect(node.right.data).toEqual(15); 15 | expect(node.right.right.data).toEqual(17); 16 | }); 17 | 18 | test('Contains returns node with the same data', () => { 19 | const node = new Node(10); 20 | node.insert(5); 21 | node.insert(15); 22 | node.insert(20); 23 | node.insert(0); 24 | node.insert(-5); 25 | node.insert(3); 26 | 27 | const three = node.left.left.right; 28 | expect(node.contains(3)).toEqual(three); 29 | }); 30 | 31 | test('Contains returns null if value not found', () => { 32 | const node = new Node(10); 33 | node.insert(5); 34 | node.insert(15); 35 | node.insert(20); 36 | node.insert(0); 37 | node.insert(-5); 38 | node.insert(3); 39 | 40 | expect(node.contains(9999)).toEqual(null); 41 | }); 42 | -------------------------------------------------------------------------------- /exercises/capitalize/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a string. The function should 3 | // capitalize the first letter of each word in the string then 4 | // return the capitalized string. 5 | // --- Examples 6 | // capitalize('a short sentence') --> 'A Short Sentence' 7 | // capitalize('a lazy fox') --> 'A Lazy Fox' 8 | // capitalize('look, it is working!') --> 'Look, It Is Working!' 9 | 10 | function capitalize(str) {} 11 | 12 | module.exports = capitalize; 13 | -------------------------------------------------------------------------------- /exercises/capitalize/test.js: -------------------------------------------------------------------------------- 1 | const capitalize = require('./index'); 2 | 3 | test('Capitalize is a function', () => { 4 | expect(typeof capitalize).toEqual('function'); 5 | }); 6 | 7 | test('capitalizes the first letter of every word in a sentence', () => { 8 | expect(capitalize('hi there, how is it going?')).toEqual( 9 | 'Hi There, How Is It Going?' 10 | ); 11 | }); 12 | 13 | test('capitalizes the first letter', () => { 14 | expect(capitalize('i love breakfast at bill miller bbq')).toEqual( 15 | 'I Love Breakfast At Bill Miller Bbq' 16 | ); 17 | }); 18 | -------------------------------------------------------------------------------- /exercises/chunk/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given an array and chunk size, divide the array into many subarrays 3 | // where each subarray is of length size 4 | // --- Examples 5 | // chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]] 6 | // chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]] 7 | // chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]] 8 | // chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]] 9 | // chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]] 10 | 11 | function chunk(array, size) {} 12 | 13 | module.exports = chunk; 14 | -------------------------------------------------------------------------------- /exercises/chunk/test.js: -------------------------------------------------------------------------------- 1 | const chunk = require('./index'); 2 | 3 | test('function chunk exists', () => { 4 | expect(typeof chunk).toEqual('function'); 5 | }); 6 | 7 | test('chunk divides an array of 10 elements with chunk size 2', () => { 8 | const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; 9 | const chunked = chunk(arr, 2); 10 | 11 | expect(chunked).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]); 12 | }); 13 | 14 | test('chunk divides an array of 3 elements with chunk size 1', () => { 15 | const arr = [1, 2, 3]; 16 | const chunked = chunk(arr, 1); 17 | 18 | expect(chunked).toEqual([[1], [2], [3]]); 19 | }); 20 | 21 | test('chunk divides an array of 5 elements with chunk size 3', () => { 22 | const arr = [1, 2, 3, 4, 5]; 23 | const chunked = chunk(arr, 3); 24 | 25 | expect(chunked).toEqual([[1, 2, 3], [4, 5]]); 26 | }); 27 | 28 | test('chunk divides an array of 13 elements with chunk size 5', () => { 29 | const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; 30 | const chunked = chunk(arr, 5); 31 | 32 | expect(chunked).toEqual([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]); 33 | }); 34 | -------------------------------------------------------------------------------- /exercises/circular/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a linked list, return true if the list 3 | // is circular, false if it is not. 4 | // --- Examples 5 | // const l = new List(); 6 | // const a = new Node('a'); 7 | // const b = new Node('b'); 8 | // const c = new Node('c'); 9 | // l.head = a; 10 | // a.next = b; 11 | // b.next = c; 12 | // c.next = b; 13 | // circular(l) // true 14 | 15 | function circular(list) {} 16 | 17 | module.exports = circular; 18 | -------------------------------------------------------------------------------- /exercises/circular/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor(values = []) { 10 | this.head = null; 11 | 12 | for (let value of values) { 13 | this.insertLast(value); 14 | } 15 | } 16 | 17 | clear() { 18 | this.head = null; 19 | } 20 | 21 | size() { 22 | let counter = 0; 23 | let node = this.head; 24 | 25 | while (node) { 26 | counter++; 27 | node = node.next; 28 | } 29 | 30 | return counter; 31 | } 32 | 33 | getAt(index) { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let counter = 0; 39 | let node = this.head; 40 | while (node) { 41 | if (counter === index) { 42 | return node; 43 | } 44 | node = node.next; 45 | counter++; 46 | } 47 | return null; 48 | } 49 | 50 | insertAt(data, index) { 51 | if (!this.head) { 52 | this.head = new Node(data); 53 | return; 54 | } 55 | 56 | if (index === 0) { 57 | this.head = new Node(data, this.head); 58 | return; 59 | } 60 | 61 | let counter = 1; 62 | let previous = this.head; 63 | let node = this.head.next; 64 | while (node) { 65 | if (counter === index) { 66 | previous.next = new Node(data, node); 67 | return; 68 | } 69 | previous = node; 70 | node = node.next; 71 | counter++; 72 | } 73 | 74 | previous.next = new Node(data, node); 75 | } 76 | 77 | removeFirst() { 78 | if (!this.head) { 79 | return; 80 | } 81 | 82 | this.head = this.head.next; 83 | } 84 | 85 | removeLast() { 86 | if (!this.head) { 87 | return; 88 | } 89 | 90 | if (!this.head.next) { 91 | this.head = null; 92 | return; 93 | } 94 | 95 | let previous = this.head; 96 | let node = this.head.next; 97 | while (node.next) { 98 | previous = node; 99 | node = node.next; 100 | } 101 | previous.next = null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | let counter = 0; 110 | let node = this.head; 111 | while (node) { 112 | if (counter === index - 1) { 113 | if (node.next) { 114 | return (node.next = node.next.next); 115 | } else { 116 | return (node.next = null); 117 | } 118 | } 119 | node = node.next; 120 | counter++; 121 | } 122 | } 123 | 124 | getFirst() { 125 | return this.head; 126 | } 127 | 128 | insertFirst(data) { 129 | this.head = new Node(data, this.getFirst()); 130 | } 131 | 132 | getLast() { 133 | if (!this.head) { 134 | return null; 135 | } 136 | 137 | let node = this.head; 138 | while (node.next) { 139 | node = node.next; 140 | } 141 | 142 | return node; 143 | } 144 | 145 | insertLast(data) { 146 | const last = this.getLast(); 147 | 148 | if (last) { 149 | last.next = new Node(data); 150 | return last.next; 151 | } else { 152 | this.head = new Node(data); 153 | return this.head; 154 | } 155 | } 156 | 157 | forEach(fn) { 158 | if (!this.head) { 159 | return null; 160 | } 161 | 162 | let node = this.head; 163 | while (node) { 164 | fn(node); 165 | node = node.next; 166 | } 167 | } 168 | 169 | *[Symbol.iterator]() { 170 | let node = this.head; 171 | while (node) { 172 | yield node; 173 | node = node.next; 174 | } 175 | } 176 | } 177 | 178 | module.exports = { Node, LinkedList }; 179 | -------------------------------------------------------------------------------- /exercises/circular/test.js: -------------------------------------------------------------------------------- 1 | const circular = require('./index'); 2 | const L = require('./linkedlist'); 3 | const List = L.LinkedList; 4 | const Node = L.Node; 5 | 6 | test('circular', () => { 7 | expect(typeof circular).toEqual('function'); 8 | }); 9 | 10 | test('circular detects circular linked lists', () => { 11 | const l = new List(); 12 | const a = new Node('a'); 13 | const b = new Node('b'); 14 | const c = new Node('c'); 15 | 16 | l.head = a; 17 | a.next = b; 18 | b.next = c; 19 | c.next = b; 20 | 21 | expect(circular(l)).toEqual(true); 22 | }); 23 | 24 | test('circular detects circular linked lists linked at the head', () => { 25 | const l = new List(); 26 | const a = new Node('a'); 27 | const b = new Node('b'); 28 | const c = new Node('c'); 29 | 30 | l.head = a; 31 | a.next = b; 32 | b.next = c; 33 | c.next = a; 34 | 35 | expect(circular(l)).toEqual(true); 36 | }); 37 | 38 | test('circular detects non-circular linked lists', () => { 39 | const l = new List(); 40 | const a = new Node('a'); 41 | const b = new Node('b'); 42 | const c = new Node('c'); 43 | 44 | l.head = a; 45 | a.next = b; 46 | b.next = c; 47 | c.next = null; 48 | 49 | expect(circular(l)).toEqual(false); 50 | }); 51 | -------------------------------------------------------------------------------- /exercises/events/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 |

Click the button

6 | 7 | 10 | 11 | -------------------------------------------------------------------------------- /exercises/events/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Create an 'eventing' library out of the 3 | // Events class. The Events class should 4 | // have methods 'on', 'trigger', and 'off'. 5 | 6 | class Events { 7 | // Register an event handler 8 | on(eventName, callback) {} 9 | 10 | // Trigger all callbacks associated 11 | // with a given eventName 12 | trigger(eventName) {} 13 | 14 | // Remove all event handlers associated 15 | // with the given eventName 16 | off(eventName) {} 17 | } 18 | 19 | module.exports = Events; 20 | -------------------------------------------------------------------------------- /exercises/events/test.js: -------------------------------------------------------------------------------- 1 | const Events = require('./index'); 2 | 3 | test('Events can be registered then triggered', () => { 4 | const events = new Events(); 5 | 6 | const cb1 = jest.fn(); 7 | 8 | events.on('click', cb1); 9 | events.trigger('click'); 10 | 11 | expect(cb1.mock.calls.length).toBe(1); 12 | }); 13 | 14 | test('Multiple events can be registered then triggered', () => { 15 | const events = new Events(); 16 | 17 | const cb1 = jest.fn(); 18 | const cb2 = jest.fn(); 19 | 20 | events.on('click', cb1); 21 | events.on('click', cb2); 22 | events.trigger('click'); 23 | 24 | expect(cb1.mock.calls.length).toBe(1); 25 | expect(cb2.mock.calls.length).toBe(1); 26 | }); 27 | 28 | test('Events can be triggered multiple times', () => { 29 | const events = new Events(); 30 | 31 | const cb1 = jest.fn(); 32 | const cb2 = jest.fn(); 33 | 34 | events.on('click', cb1); 35 | events.trigger('click'); 36 | events.on('click', cb2); 37 | events.trigger('click'); 38 | events.trigger('click'); 39 | 40 | expect(cb1.mock.calls.length).toBe(3); 41 | expect(cb2.mock.calls.length).toBe(2); 42 | }); 43 | 44 | test('Events can have different names', () => { 45 | const events = new Events(); 46 | 47 | const cb1 = jest.fn(); 48 | const cb2 = jest.fn(); 49 | 50 | events.on('click', cb1); 51 | events.trigger('click'); 52 | events.on('hover', cb2); 53 | events.trigger('click'); 54 | events.trigger('hover'); 55 | 56 | expect(cb1.mock.calls.length).toBe(2); 57 | expect(cb2.mock.calls.length).toBe(1); 58 | }); 59 | 60 | test('Events can be toggled off', () => { 61 | const events = new Events(); 62 | 63 | const cb1 = jest.fn(); 64 | const cb2 = jest.fn(); 65 | 66 | events.on('hover', cb2); 67 | 68 | events.on('click', cb1); 69 | events.trigger('click'); 70 | events.off('click'); 71 | events.trigger('click'); 72 | 73 | events.trigger('hover'); 74 | 75 | expect(cb1.mock.calls.length).toBe(1); 76 | expect(cb2.mock.calls.length).toBe(1); 77 | }); 78 | -------------------------------------------------------------------------------- /exercises/fib/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Print out the n-th entry in the fibonacci series. 3 | // The fibonacci series is an ordering of numbers where 4 | // each number is the sum of the preceeding two. 5 | // For example, the sequence 6 | // [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] 7 | // forms the first ten entries of the fibonacci series. 8 | // Example: 9 | // fib(4) === 3 10 | 11 | function fib(n) {} 12 | 13 | module.exports = fib; 14 | -------------------------------------------------------------------------------- /exercises/fib/test.js: -------------------------------------------------------------------------------- 1 | const fib = require('./index'); 2 | 3 | test('Fib function is defined', () => { 4 | expect(typeof fib).toEqual('function'); 5 | }); 6 | 7 | test('calculates correct fib value for 1', () => { 8 | expect(fib(1)).toEqual(1); 9 | }); 10 | 11 | test('calculates correct fib value for 2', () => { 12 | expect(fib(2)).toEqual(1); 13 | }); 14 | 15 | test('calculates correct fib value for 3', () => { 16 | expect(fib(3)).toEqual(2); 17 | }); 18 | 19 | test('calculates correct fib value for 4', () => { 20 | expect(fib(4)).toEqual(3); 21 | }); 22 | 23 | test('calculates correct fib value for 15', () => { 24 | expect(fib(39)).toEqual(63245986); 25 | }); 26 | -------------------------------------------------------------------------------- /exercises/fizzbuzz/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a program that console logs the numbers 3 | // from 1 to n. But for multiples of three print 4 | // “fizz” instead of the number and for the multiples 5 | // of five print “buzz”. For numbers which are multiples 6 | // of both three and five print “fizzbuzz”. 7 | // --- Example 8 | // fizzBuzz(5); 9 | // 1 10 | // 2 11 | // fizz 12 | // 4 13 | // buzz 14 | 15 | function fizzBuzz(n) {} 16 | 17 | module.exports = fizzBuzz; 18 | -------------------------------------------------------------------------------- /exercises/fizzbuzz/test.js: -------------------------------------------------------------------------------- 1 | const fizzBuzz = require('./index'); 2 | 3 | test('fizzBuzz function is defined', () => { 4 | expect(fizzBuzz).toBeDefined(); 5 | }); 6 | 7 | test('Calling fizzbuzz with `5` prints out 5 statements', () => { 8 | fizzBuzz(5); 9 | 10 | expect(console.log.mock.calls.length).toEqual(5); 11 | }); 12 | 13 | test('Calling fizzbuzz with 15 prints out the correct values', () => { 14 | fizzBuzz(15); 15 | 16 | expect(console.log.mock.calls[0][0]).toEqual(1); 17 | expect(console.log.mock.calls[1][0]).toEqual(2); 18 | expect(console.log.mock.calls[2][0]).toEqual('fizz'); 19 | expect(console.log.mock.calls[3][0]).toEqual(4); 20 | expect(console.log.mock.calls[4][0]).toEqual('buzz'); 21 | expect(console.log.mock.calls[5][0]).toEqual('fizz'); 22 | expect(console.log.mock.calls[6][0]).toEqual(7); 23 | expect(console.log.mock.calls[7][0]).toEqual(8); 24 | expect(console.log.mock.calls[8][0]).toEqual('fizz'); 25 | expect(console.log.mock.calls[9][0]).toEqual('buzz'); 26 | expect(console.log.mock.calls[10][0]).toEqual(11); 27 | expect(console.log.mock.calls[11][0]).toEqual('fizz'); 28 | expect(console.log.mock.calls[12][0]).toEqual(13); 29 | expect(console.log.mock.calls[13][0]).toEqual(14); 30 | expect(console.log.mock.calls[14][0]).toEqual('fizzbuzz'); 31 | }); 32 | 33 | beforeEach(() => { 34 | jest.spyOn(console, 'log'); 35 | }); 36 | 37 | afterEach(() => { 38 | console.log.mockRestore(); 39 | }); 40 | -------------------------------------------------------------------------------- /exercises/fromlast/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a linked list, return the element n spaces 3 | // from the last node in the list. Do not call the 'size' 4 | // method of the linked list. Assume that n will always 5 | // be less than the length of the list. 6 | // --- Examples 7 | // const list = new List(); 8 | // list.insertLast('a'); 9 | // list.insertLast('b'); 10 | // list.insertLast('c'); 11 | // list.insertLast('d'); 12 | // fromLast(list, 2).data // 'b' 13 | 14 | function fromLast(list, n) {} 15 | 16 | module.exports = fromLast; 17 | -------------------------------------------------------------------------------- /exercises/fromlast/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor() { 10 | this.head = null; 11 | } 12 | 13 | insertFirst(data) { 14 | this.head = new Node(data, this.head); 15 | } 16 | 17 | size() { 18 | let counter = 0; 19 | let node = this.head; 20 | 21 | while (node) { 22 | counter++; 23 | node = node.next; 24 | } 25 | 26 | return counter; 27 | } 28 | 29 | getFirst() { 30 | return this.head; 31 | } 32 | 33 | getLast() { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let node = this.head; 39 | while (node) { 40 | if (!node.next) { 41 | return node; 42 | } 43 | node = node.next; 44 | } 45 | } 46 | 47 | clear() { 48 | this.head = null; 49 | } 50 | 51 | removeFirst() { 52 | if (!this.head) { 53 | return; 54 | } 55 | 56 | this.head = this.head.next; 57 | } 58 | 59 | removeLast() { 60 | if (!this.head) { 61 | return; 62 | } 63 | 64 | if (!this.head.next) { 65 | this.head = null; 66 | return; 67 | } 68 | 69 | let previous = this.head; 70 | let node = this.head.next; 71 | while (node.next) { 72 | previous = node; 73 | node = node.next; 74 | } 75 | previous.next = null; 76 | } 77 | 78 | insertLast(data) { 79 | const last = this.getLast(); 80 | 81 | if (last) { 82 | // There are some existing nodes in our chain 83 | last.next = new Node(data); 84 | } else { 85 | // The chain is empty! 86 | this.head = new Node(data); 87 | } 88 | } 89 | 90 | getAt(index) { 91 | let counter = 0; 92 | let node = this.head; 93 | while (node) { 94 | if (counter === index) { 95 | return node; 96 | } 97 | 98 | counter++; 99 | node = node.next; 100 | } 101 | return null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | if (index === 0) { 110 | this.head = this.head.next; 111 | return; 112 | } 113 | 114 | const previous = this.getAt(index - 1); 115 | if (!previous || !previous.next) { 116 | return; 117 | } 118 | previous.next = previous.next.next; 119 | } 120 | 121 | insertAt(data, index) { 122 | if (!this.head) { 123 | this.head = new Node(data); 124 | return; 125 | } 126 | 127 | if (index === 0) { 128 | this.head = new Node(data, this.head); 129 | return; 130 | } 131 | 132 | const previous = this.getAt(index - 1) || this.getLast(); 133 | const node = new Node(data, previous.next); 134 | previous.next = node; 135 | } 136 | 137 | forEach(fn) { 138 | let node = this.head; 139 | let counter = 0; 140 | while (node) { 141 | fn(node, counter); 142 | node = node.next; 143 | counter++; 144 | } 145 | } 146 | 147 | *[Symbol.iterator]() { 148 | let node = this.head; 149 | while (node) { 150 | yield node; 151 | node = node.next; 152 | } 153 | } 154 | } 155 | 156 | module.exports = { Node, LinkedList }; 157 | -------------------------------------------------------------------------------- /exercises/fromlast/test.js: -------------------------------------------------------------------------------- 1 | const fromLast = require('./index'); 2 | const L = require('./linkedlist'); 3 | const List = L.LinkedList; 4 | const Node = L.Node; 5 | 6 | test('fromLast is a function', () => { 7 | expect(typeof fromLast).toEqual('function'); 8 | }); 9 | 10 | test('fromLast returns the node n elements from the end', () => { 11 | const l = new List(); 12 | 13 | l.insertLast('a'); 14 | l.insertLast('b'); 15 | l.insertLast('c'); 16 | l.insertLast('d'); 17 | l.insertLast('e'); 18 | 19 | expect(fromLast(l, 3).data).toEqual('b'); 20 | }); 21 | -------------------------------------------------------------------------------- /exercises/levelwidth/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given the root node of a tree, return 3 | // an array where each element is the width 4 | // of the tree at each level. 5 | // --- Example 6 | // Given: 7 | // 0 8 | // / | \ 9 | // 1 2 3 10 | // | | 11 | // 4 5 12 | // Answer: [1, 3, 2] 13 | 14 | function levelWidth(root) {} 15 | 16 | module.exports = levelWidth; 17 | -------------------------------------------------------------------------------- /exercises/levelwidth/node.js: -------------------------------------------------------------------------------- 1 | module.exports = class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.children = []; 5 | } 6 | 7 | add(data) { 8 | this.children.push(new Node(data)); 9 | } 10 | }; 11 | -------------------------------------------------------------------------------- /exercises/levelwidth/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./node'); 2 | const levelWidth = require('./index'); 3 | 4 | test('levelWidth is a function', () => { 5 | expect(typeof levelWidth).toEqual('function'); 6 | }); 7 | 8 | test('levelWidth returns number of nodes at widest point', () => { 9 | const root = new Node(0); 10 | root.add(1); 11 | root.add(2); 12 | root.add(3); 13 | root.children[0].add(4); 14 | root.children[2].add(5); 15 | 16 | expect(levelWidth(root)).toEqual([1, 3, 2]); 17 | }); 18 | 19 | test('levelWidth returns number of nodes at widest point', () => { 20 | const root = new Node(0); 21 | root.add(1); 22 | root.children[0].add(2); 23 | root.children[0].add(3); 24 | root.children[0].children[0].add(4); 25 | 26 | expect(levelWidth(root)).toEqual([1, 1, 2, 1]); 27 | }); 28 | -------------------------------------------------------------------------------- /exercises/linkedlist/directions.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 |

Node Class API

12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 35 | 44 | 45 | 46 |
FunctionArgumentsReturnsDirectionsExample
Node.constructor(Data, Node)Node 28 | Creates a class instance to represent a node. The node should 29 | have two properties, 'data' and 'next'. Accept both 30 | of these as arguments to the 'Node' constructor, then 31 | assign them to the instance as properties 'data' and 'next'. 32 | If 'next' is not provided to the constructor, then default its 33 | value to be 'null'. 34 | 36 |
 37 |             const n = new Node('There');
 38 |             n.data // 'Hi'
 39 |             n.next // null
 40 |             const n2 = new Node('Hi', n);
 41 |             n.next // returns n
 42 |           
43 |
47 | 48 |

LinkedList Class API

49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 71 | 77 | 78 | 79 | 80 | 81 | 82 | 87 | 93 | 94 | 95 | 96 | 97 | 98 | 101 | 110 | 111 | 112 | 113 | 114 | 115 | 118 | 126 | 127 | 128 | 131 | 134 | 137 | 140 | 148 | 149 | 150 | 153 | 156 | 159 | 162 | 171 | 172 | 173 | 176 | 179 | 182 | 186 | 195 | 196 | 197 | 200 | 203 | 206 | 209 | 219 | 220 | 221 | 224 | 227 | 230 | 233 | 242 | 243 | 244 | 247 | 250 | 253 | 256 | 265 | 266 | 267 | 270 | 273 | 276 | 279 | 289 | 290 | 291 | 294 | 297 | 300 | 305 | 315 | 316 | 317 | 320 | 323 | 326 | 329 | 344 | 345 | 346 | 349 | 352 | 355 | 358 | 374 | 375 | 376 |
FunctionArgumentsReturnsDirectionsExample
constructor-(LinkedList) 65 | Create a class to represent a linked list. When created, 66 | a linked list should have *no* head node associated with it. 67 | The LinkedList instance will have one property, 'head', which 68 | is a reference to the first node of the linked list. By default 69 | 'head' should be 'null'. 70 | 72 |
 73 |             const list = new LinkedList();
 74 |             list.head // null
 75 |           
76 |
insertFirst(data)- 83 | Creates a new Node from argument 'data' and assigns the resulting 84 | node to the 'head' property. Make sure to handle the case in which 85 | the linked list already has a node assigned to the 'head' property. 86 | 88 |
 89 |             const list = new LinkedList();
 90 |             list.insertFirst('Hi There'); // List has one node
 91 |           
92 |
size-(integer) 99 | Returns the number of nodes in the linked list. 100 | 102 |
103 |             const list = new LinkedList();
104 |             list.insertFirst('a');
105 |             list.insertFirst('b');
106 |             list.insertFirst('c');
107 |             list.size(); // returns 3
108 |           
109 |
getFirst-(Node) 116 | Returns the first node of the linked list. 117 | 119 |
120 |             const list = new LinkedList();
121 |             list.insertFirst('a');
122 |             list.insertFirst('b');
123 |             list.getFirst(); // returns Node instance with data 'a'
124 |           
125 |
129 | getLast 130 | 132 | - 133 | 135 | (Node) 136 | 138 | Returns the last node of the linked list 139 | 141 |
142 |             const list = new LinkedList();
143 |             list.insertFirst('a');
144 |             list.insertFirst('b');
145 |             list.getLast(); // returns node with data 'a'
146 |           
147 |
151 | clear 152 | 154 | - 155 | 157 | - 158 | 160 | Empties the linked list of any nodes. 161 | 163 |
164 |             const list = new LinkedList();
165 |             list.insertFirst('a');
166 |             list.insertFirst('b');
167 |             list.clear();
168 |             list.size(); // returns 0
169 |           
170 |
174 | removeFirst 175 | 177 | - 178 | 180 | - 181 | 183 | Removes only the first node of the linked list. The list's head should 184 | now be the second element. 185 | 187 |
188 |             const list = new LinkedList();
189 |             list.insertFirst('a');
190 |             list.insertFirst('b');
191 |             list.removeFirst();
192 |             list.getFirst(); // returns node with data 'a'
193 |           
194 |
198 | removeLast 199 | 201 | - 202 | 204 | - 205 | 207 | Removes the last node of the chain 208 | 210 |
211 |             const list = new LinkedList();
212 |             list.insertFirst('a');
213 |             list.insertFirst('b');
214 |             list.removeLast();
215 |             list.size(); // returns 1
216 |             list.getLast(); // returns node with data of 'b'
217 |           
218 |
222 | insertLast 223 | 225 | (Data) 226 | 228 | - 229 | 231 | Inserts a new node with provided data at the end of the chain 232 | 234 |
235 |             const list = new LinkedList();
236 |             list.insertFirst('a');
237 |             list.insertFirst('b');
238 |             list.insertLast('c');
239 |             list.getLast(); // returns node with data 'C'
240 |           
241 |
245 | getAt 246 | 248 | (integer) 249 | 251 | (Node) 252 | 254 | Returns the node at the provided index 255 | 257 |
258 |             const list = new List();
259 |             list.insertFirst('a');
260 |             list.insertFirst('b');
261 |             list.insertFirst('c');
262 |             list.getAt(1); // returns node with data 'b'
263 |           
264 |
268 | removeAt 269 | 271 | (integer) 272 | 274 | - 275 | 277 | Removes node at the provided index 278 | 280 |
281 |             const list = new List();
282 |             list.insertFirst('a');
283 |             list.insertFirst('b');
284 |             list.insertFirst('c');
285 |             list.removeAt(1);
286 |             list.getAt(1); // returns node with data 'a'
287 |           
288 |
292 | insertAt 293 | 295 | (Data, integer) 296 | 298 | - 299 | 301 | Create an insert a new node at provided index. 302 | If index is out of bounds, add the node to the end 303 | of the list. 304 | 306 |
307 |             const list = new List();
308 |             list.insertFirst('a');
309 |             list.insertFirst('b');
310 |             list.insertFirst('c');
311 |             list.insertAt('Hi', 1)
312 |             list.getAt(1); // returns node with data 'Hi'
313 |           
314 |
318 | forEach 319 | 321 | (function) 322 | 324 | - 325 | 327 | Calls the provided function with every node of the chain 328 | 330 |
331 |             const list = new List();
332 | 
333 |             list.insertLast(1);
334 |             list.insertLast(2);
335 |             list.insertLast(3);
336 |             list.insertLast(4);
337 | 
338 |             list.forEach(node => {
339 |               node.data += 10;
340 |             });
341 |             list.getAt(0); // Returns node with data '11'
342 |           
343 |
347 | for...of Loop 348 | 350 | - 351 | 353 | - 354 | 356 | Linked list should be compatible as the subject of a 'for...of' loop 357 | 359 |
360 |             const list = new List();
361 | 
362 |             list.insertLast(1);
363 |             list.insertLast(2);
364 |             list.insertLast(3);
365 |             list.insertLast(4);
366 | 
367 |             for (let node of list) {
368 |               node.data += 10;
369 |             }
370 | 
371 |             node.getAt(1); // returns node with data 11
372 |           
373 |
377 | 378 | -------------------------------------------------------------------------------- /exercises/linkedlist/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement classes Node and Linked Lists 3 | // See 'directions' document 4 | 5 | class Node {} 6 | 7 | class LinkedList {} 8 | 9 | module.exports = { Node, LinkedList }; 10 | -------------------------------------------------------------------------------- /exercises/linkedlist/test.js: -------------------------------------------------------------------------------- 1 | const L = require('./index'); 2 | const List = L.LinkedList; 3 | const Node = L.Node; 4 | 5 | test('List is a class', () => { 6 | expect(typeof List.prototype.constructor).toEqual('function'); 7 | }); 8 | 9 | test('Node is a class', () => { 10 | expect(typeof Node.prototype.constructor).toEqual('function'); 11 | }); 12 | 13 | describe.skip('A Node', () => { 14 | test('has properties "data" and "next"', () => { 15 | const node = new Node('a', 'b'); 16 | expect(node.data).toEqual('a'); 17 | expect(node.next).toEqual('b'); 18 | }); 19 | }); 20 | 21 | describe.skip('Insert First', () => { 22 | test('appends a node to the start of the list', () => { 23 | const l = new List(); 24 | l.insertFirst(1); 25 | expect(l.head.data).toEqual(1); 26 | l.insertFirst(2); 27 | expect(l.head.data).toEqual(2); 28 | }); 29 | }); 30 | 31 | describe.skip('Size', () => { 32 | test('returns the number of items in the linked list', () => { 33 | const l = new List(); 34 | expect(l.size()).toEqual(0); 35 | l.insertFirst(1); 36 | l.insertFirst(1); 37 | l.insertFirst(1); 38 | l.insertFirst(1); 39 | expect(l.size()).toEqual(4); 40 | }); 41 | }); 42 | 43 | describe.skip('GetFirst', () => { 44 | test('returns the first element', () => { 45 | const l = new List(); 46 | l.insertFirst(1); 47 | expect(l.getFirst().data).toEqual(1); 48 | l.insertFirst(2); 49 | expect(l.getFirst().data).toEqual(2); 50 | }); 51 | }); 52 | 53 | describe.skip('GetLast', () => { 54 | test('returns the last element', () => { 55 | const l = new List(); 56 | l.insertFirst(2); 57 | expect(l.getLast()).toEqual({ data: 2, next: null }); 58 | l.insertFirst(1); 59 | expect(l.getLast()).toEqual({ data: 2, next: null }); 60 | }); 61 | }); 62 | 63 | describe.skip('Clear', () => { 64 | test('empties out the list', () => { 65 | const l = new List(); 66 | expect(l.size()).toEqual(0); 67 | l.insertFirst(1); 68 | l.insertFirst(1); 69 | l.insertFirst(1); 70 | l.insertFirst(1); 71 | expect(l.size()).toEqual(4); 72 | l.clear(); 73 | expect(l.size()).toEqual(0); 74 | }); 75 | }); 76 | 77 | describe.skip('RemoveFirst', () => { 78 | test('removes the first node when the list has a size of one', () => { 79 | const l = new List(); 80 | l.insertFirst('a'); 81 | l.removeFirst(); 82 | expect(l.size()).toEqual(0); 83 | expect(l.getFirst()).toEqual(null); 84 | }); 85 | 86 | test('removes the first node when the list has a size of three', () => { 87 | const l = new List(); 88 | l.insertFirst('c'); 89 | l.insertFirst('b'); 90 | l.insertFirst('a'); 91 | l.removeFirst(); 92 | expect(l.size()).toEqual(2); 93 | expect(l.getFirst().data).toEqual('b'); 94 | l.removeFirst(); 95 | expect(l.size()).toEqual(1); 96 | expect(l.getFirst().data).toEqual('c'); 97 | }); 98 | }); 99 | 100 | describe.skip('RemoveLast', () => { 101 | test('RemoveLast removes the last node when list is empty', () => { 102 | const l = new List(); 103 | expect(() => { 104 | l.removeLast(); 105 | }).not.toThrow(); 106 | }); 107 | 108 | test('RemoveLast removes the last node when list is length 1', () => { 109 | const l = new List(); 110 | l.insertFirst('a'); 111 | l.removeLast(); 112 | expect(l.head).toEqual(null); 113 | }); 114 | 115 | test('RemoveLast removes the last node when list is length 2', () => { 116 | const l = new List(); 117 | l.insertFirst('b'); 118 | l.insertFirst('a'); 119 | 120 | l.removeLast(); 121 | 122 | expect(l.size()).toEqual(1); 123 | expect(l.head.data).toEqual('a'); 124 | }); 125 | 126 | test('RemoveLast removes the last node when list is length 3', () => { 127 | const l = new List(); 128 | l.insertFirst('c'); 129 | l.insertFirst('b'); 130 | l.insertFirst('a'); 131 | l.removeLast(); 132 | 133 | expect(l.size()).toEqual(2); 134 | expect(l.getLast().data).toEqual('b'); 135 | }); 136 | }); 137 | 138 | describe.skip('InsertLast', () => { 139 | test('adds to the end of the list', () => { 140 | const l = new List(); 141 | l.insertFirst('a'); 142 | 143 | l.insertLast('b'); 144 | 145 | expect(l.size()).toEqual(2); 146 | expect(l.getLast().data).toEqual('b'); 147 | }); 148 | }); 149 | 150 | describe.skip('GetAt', () => { 151 | test('returns the node at given index', () => { 152 | const l = new List(); 153 | expect(l.getAt(10)).toEqual(null); 154 | 155 | l.insertLast(1); 156 | l.insertLast(2); 157 | l.insertLast(3); 158 | l.insertLast(4); 159 | 160 | expect(l.getAt(0).data).toEqual(1); 161 | expect(l.getAt(1).data).toEqual(2); 162 | expect(l.getAt(2).data).toEqual(3); 163 | expect(l.getAt(3).data).toEqual(4); 164 | }); 165 | }); 166 | 167 | describe.skip('RemoveAt', () => { 168 | test('removeAt doesnt crash on an empty list', () => { 169 | const l = new List(); 170 | expect(() => { 171 | l.removeAt(0); 172 | l.removeAt(1); 173 | l.removeAt(2); 174 | }).not.toThrow(); 175 | }); 176 | 177 | test('removeAt doesnt crash on an index out of bounds', () => { 178 | const l = new List(); 179 | expect(() => { 180 | const l = new List(); 181 | l.insertFirst('a'); 182 | l.removeAt(1); 183 | }).not.toThrow(); 184 | }); 185 | 186 | test('removeAt deletes the first node', () => { 187 | const l = new List(); 188 | l.insertLast(1); 189 | l.insertLast(2); 190 | l.insertLast(3); 191 | l.insertLast(4); 192 | expect(l.getAt(0).data).toEqual(1); 193 | l.removeAt(0); 194 | expect(l.getAt(0).data).toEqual(2); 195 | }); 196 | 197 | test('removeAt deletes the node at the given index', () => { 198 | const l = new List(); 199 | l.insertLast(1); 200 | l.insertLast(2); 201 | l.insertLast(3); 202 | l.insertLast(4); 203 | expect(l.getAt(1).data).toEqual(2); 204 | l.removeAt(1); 205 | expect(l.getAt(1).data).toEqual(3); 206 | }); 207 | 208 | test('removeAt works on the last node', () => { 209 | const l = new List(); 210 | l.insertLast(1); 211 | l.insertLast(2); 212 | l.insertLast(3); 213 | l.insertLast(4); 214 | expect(l.getAt(3).data).toEqual(4); 215 | l.removeAt(3); 216 | expect(l.getAt(3)).toEqual(null); 217 | }); 218 | }); 219 | 220 | describe.skip('InsertAt', () => { 221 | test('inserts a new node with data at the 0 index when the list is empty', () => { 222 | const l = new List(); 223 | l.insertAt('hi', 0); 224 | expect(l.getFirst().data).toEqual('hi'); 225 | }); 226 | 227 | test('inserts a new node with data at the 0 index when the list has elements', () => { 228 | const l = new List(); 229 | l.insertLast('a'); 230 | l.insertLast('b'); 231 | l.insertLast('c'); 232 | l.insertAt('hi', 0); 233 | expect(l.getAt(0).data).toEqual('hi'); 234 | expect(l.getAt(1).data).toEqual('a'); 235 | expect(l.getAt(2).data).toEqual('b'); 236 | expect(l.getAt(3).data).toEqual('c'); 237 | }); 238 | 239 | test('inserts a new node with data at a middle index', () => { 240 | const l = new List(); 241 | l.insertLast('a'); 242 | l.insertLast('b'); 243 | l.insertLast('c'); 244 | l.insertLast('d'); 245 | l.insertAt('hi', 2); 246 | expect(l.getAt(0).data).toEqual('a'); 247 | expect(l.getAt(1).data).toEqual('b'); 248 | expect(l.getAt(2).data).toEqual('hi'); 249 | expect(l.getAt(3).data).toEqual('c'); 250 | expect(l.getAt(4).data).toEqual('d'); 251 | }); 252 | 253 | test('inserts a new node with data at a last index', () => { 254 | const l = new List(); 255 | l.insertLast('a'); 256 | l.insertLast('b'); 257 | l.insertAt('hi', 2); 258 | expect(l.getAt(0).data).toEqual('a'); 259 | expect(l.getAt(1).data).toEqual('b'); 260 | expect(l.getAt(2).data).toEqual('hi'); 261 | }); 262 | 263 | test('insert a new node when index is out of bounds', () => { 264 | const l = new List(); 265 | l.insertLast('a'); 266 | l.insertLast('b'); 267 | l.insertAt('hi', 30); 268 | 269 | expect(l.getAt(0).data).toEqual('a'); 270 | expect(l.getAt(1).data).toEqual('b'); 271 | expect(l.getAt(2).data).toEqual('hi'); 272 | }); 273 | }); 274 | 275 | describe.skip('ForEach', () => { 276 | test('applies a transform to each node', () => { 277 | const l = new List(); 278 | 279 | l.insertLast(1); 280 | l.insertLast(2); 281 | l.insertLast(3); 282 | l.insertLast(4); 283 | 284 | l.forEach(node => { 285 | node.data += 10; 286 | }); 287 | 288 | expect(l.getAt(0).data).toEqual(11); 289 | expect(l.getAt(1).data).toEqual(12); 290 | expect(l.getAt(2).data).toEqual(13); 291 | expect(l.getAt(3).data).toEqual(14); 292 | }); 293 | }); 294 | 295 | describe.skip('for...of loops', () => { 296 | test('works with the linked list', () => { 297 | const l = new List(); 298 | 299 | l.insertLast(1); 300 | l.insertLast(2); 301 | l.insertLast(3); 302 | l.insertLast(4); 303 | 304 | for (let node of l) { 305 | node.data += 10; 306 | } 307 | 308 | expect(l.getAt(0).data).toEqual(11); 309 | expect(l.getAt(1).data).toEqual(12); 310 | expect(l.getAt(2).data).toEqual(13); 311 | expect(l.getAt(3).data).toEqual(14); 312 | }); 313 | 314 | test('for...of works on an empty list', () => { 315 | const l = new List(); 316 | expect(() => { 317 | for (let node of l) { 318 | } 319 | }).not.toThrow(); 320 | }); 321 | }); 322 | -------------------------------------------------------------------------------- /exercises/matrix/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts an integer N 3 | // and returns a NxN spiral matrix. 4 | // --- Examples 5 | // matrix(2) 6 | // [[1, 2], 7 | // [4, 3]] 8 | // matrix(3) 9 | // [[1, 2, 3], 10 | // [8, 9, 4], 11 | // [7, 6, 5]] 12 | // matrix(4) 13 | // [[1, 2, 3, 4], 14 | // [12, 13, 14, 5], 15 | // [11, 16, 15, 6], 16 | // [10, 9, 8, 7]] 17 | 18 | function matrix(n) {} 19 | 20 | module.exports = matrix; 21 | -------------------------------------------------------------------------------- /exercises/matrix/test.js: -------------------------------------------------------------------------------- 1 | const matrix = require('./index'); 2 | 3 | test('matrix is a function', () => { 4 | expect(typeof matrix).toEqual('function'); 5 | }); 6 | 7 | test('matrix produces a 2x2 array', () => { 8 | const m = matrix(2); 9 | expect(m.length).toEqual(2); 10 | expect(m[0]).toEqual([1, 2]); 11 | expect(m[1]).toEqual([4, 3]); 12 | }); 13 | 14 | test('matrix produces a 3x3 array', () => { 15 | const m = matrix(3); 16 | expect(m.length).toEqual(3); 17 | expect(m[0]).toEqual([1, 2, 3]); 18 | expect(m[1]).toEqual([8, 9, 4]); 19 | expect(m[2]).toEqual([7, 6, 5]); 20 | }); 21 | 22 | test('matrix produces a 4x4 array', () => { 23 | const m = matrix(4); 24 | expect(m.length).toEqual(4); 25 | expect(m[0]).toEqual([1, 2, 3, 4]); 26 | expect(m[1]).toEqual([12, 13, 14, 5]); 27 | expect(m[2]).toEqual([11, 16, 15, 6]); 28 | expect(m[3]).toEqual([10, 9, 8, 7]); 29 | }); 30 | -------------------------------------------------------------------------------- /exercises/maxchar/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return the character that is most 3 | // commonly used in the string. 4 | // --- Examples 5 | // maxChar("abcccccccd") === "c" 6 | // maxChar("apple 1231111") === "1" 7 | 8 | function maxChar(str) {} 9 | 10 | module.exports = maxChar; 11 | -------------------------------------------------------------------------------- /exercises/maxchar/test.js: -------------------------------------------------------------------------------- 1 | const maxChar = require('./index'); 2 | 3 | test('maxChar function exists', () => { 4 | expect(typeof maxChar).toEqual('function'); 5 | }); 6 | 7 | test('Finds the most frequently used char', () => { 8 | expect(maxChar('a')).toEqual('a'); 9 | expect(maxChar('abcdefghijklmnaaaaa')).toEqual('a'); 10 | }); 11 | 12 | test('Works with numbers in the string', () => { 13 | expect(maxChar('ab1c1d1e1f1g1')).toEqual('1'); 14 | }); 15 | -------------------------------------------------------------------------------- /exercises/midpoint/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Return the 'middle' node of a linked list. 3 | // If the list has an even number of elements, return 4 | // the node at the end of the first half of the list. 5 | // *Do not* use a counter variable, *do not* retrieve 6 | // the size of the list, and only iterate 7 | // through the list one time. 8 | // --- Example 9 | // const l = new LinkedList(); 10 | // l.insertLast('a') 11 | // l.insertLast('b') 12 | // l.insertLast('c') 13 | // midpoint(l); // returns { data: 'b' } 14 | 15 | function midpoint(list) {} 16 | 17 | module.exports = midpoint; 18 | -------------------------------------------------------------------------------- /exercises/midpoint/linkedlist.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data, next = null) { 3 | this.data = data; 4 | this.next = next; 5 | } 6 | } 7 | 8 | class LinkedList { 9 | constructor(values = []) { 10 | this.head = null; 11 | 12 | for (let value of values) { 13 | this.insertLast(value); 14 | } 15 | } 16 | 17 | clear() { 18 | this.head = null; 19 | } 20 | 21 | size() { 22 | let counter = 0; 23 | let node = this.head; 24 | 25 | while (node) { 26 | counter++; 27 | node = node.next; 28 | } 29 | 30 | return counter; 31 | } 32 | 33 | getAt(index) { 34 | if (!this.head) { 35 | return null; 36 | } 37 | 38 | let counter = 0; 39 | let node = this.head; 40 | while (node) { 41 | if (counter === index) { 42 | return node; 43 | } 44 | node = node.next; 45 | counter++; 46 | } 47 | return null; 48 | } 49 | 50 | insertAt(data, index) { 51 | if (!this.head) { 52 | this.head = new Node(data); 53 | return; 54 | } 55 | 56 | if (index === 0) { 57 | this.head = new Node(data, this.head); 58 | return; 59 | } 60 | 61 | let counter = 1; 62 | let previous = this.head; 63 | let node = this.head.next; 64 | while (node) { 65 | if (counter === index) { 66 | previous.next = new Node(data, node); 67 | return; 68 | } 69 | previous = node; 70 | node = node.next; 71 | counter++; 72 | } 73 | 74 | previous.next = new Node(data, node); 75 | } 76 | 77 | removeFirst() { 78 | if (!this.head) { 79 | return; 80 | } 81 | 82 | this.head = this.head.next; 83 | } 84 | 85 | removeLast() { 86 | if (!this.head) { 87 | return; 88 | } 89 | 90 | if (!this.head.next) { 91 | this.head = null; 92 | return; 93 | } 94 | 95 | let previous = this.head; 96 | let node = this.head.next; 97 | while (node.next) { 98 | previous = node; 99 | node = node.next; 100 | } 101 | previous.next = null; 102 | } 103 | 104 | removeAt(index) { 105 | if (!this.head) { 106 | return; 107 | } 108 | 109 | let counter = 0; 110 | let node = this.head; 111 | while (node) { 112 | if (counter === index - 1) { 113 | if (node.next) { 114 | return (node.next = node.next.next); 115 | } else { 116 | return (node.next = null); 117 | } 118 | } 119 | node = node.next; 120 | counter++; 121 | } 122 | } 123 | 124 | getFirst() { 125 | return this.head; 126 | } 127 | 128 | insertFirst(data) { 129 | this.head = new Node(data, this.getFirst()); 130 | } 131 | 132 | getLast() { 133 | if (!this.head) { 134 | return null; 135 | } 136 | 137 | let node = this.head; 138 | while (node.next) { 139 | node = node.next; 140 | } 141 | 142 | return node; 143 | } 144 | 145 | insertLast(data) { 146 | const last = this.getLast(); 147 | 148 | if (last) { 149 | last.next = new Node(data); 150 | return last.next; 151 | } else { 152 | this.head = new Node(data); 153 | return this.head; 154 | } 155 | } 156 | 157 | forEach(fn) { 158 | if (!this.head) { 159 | return null; 160 | } 161 | 162 | let node = this.head; 163 | while (node) { 164 | fn(node); 165 | node = node.next; 166 | } 167 | } 168 | 169 | *[Symbol.iterator]() { 170 | let node = this.head; 171 | while (node) { 172 | yield node; 173 | node = node.next; 174 | } 175 | } 176 | } 177 | 178 | module.exports = { Node, LinkedList }; 179 | -------------------------------------------------------------------------------- /exercises/midpoint/test.js: -------------------------------------------------------------------------------- 1 | const midpoint = require('./index'); 2 | const L = require('./linkedlist'); 3 | const Node = L.Node; 4 | const LinkedList = L.LinkedList; 5 | 6 | test('Midpoint is a function', () => { 7 | expect(typeof midpoint).toEqual('function'); 8 | }); 9 | 10 | describe('Midpoint returns the middle node of an odd numbered list', () => { 11 | test('when the list has 3 elements', () => { 12 | const l = new LinkedList(); 13 | l.insertLast('a'); 14 | l.insertLast('b'); 15 | l.insertLast('c'); 16 | expect(midpoint(l).data).toEqual('b'); 17 | }); 18 | 19 | test('when the list has 5 elements', () => { 20 | const l = new LinkedList(); 21 | l.insertLast('a'); 22 | l.insertLast('b'); 23 | l.insertLast('c'); 24 | l.insertLast('d'); 25 | l.insertLast('e'); 26 | expect(midpoint(l).data).toEqual('c'); 27 | }); 28 | }); 29 | 30 | describe('Midpoint returns the middle node of an even numbered list', () => { 31 | test('when the list has 2 elements', () => { 32 | const l = new LinkedList(); 33 | l.insertLast('a'); 34 | l.insertLast('b'); 35 | expect(midpoint(l).data).toEqual('a'); 36 | }); 37 | 38 | test('when the list has 4 elements', () => { 39 | const l = new LinkedList(); 40 | l.insertLast('a'); 41 | l.insertLast('b'); 42 | l.insertLast('c'); 43 | l.insertLast('d'); 44 | expect(midpoint(l).data).toEqual('b'); 45 | }); 46 | }); 47 | -------------------------------------------------------------------------------- /exercises/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "dev", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "jest": { 10 | "testEnvironment": "node" 11 | }, 12 | "author": "stephen grider", 13 | "license": "ISC" 14 | } 15 | -------------------------------------------------------------------------------- /exercises/palindrome/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return true if the string is a palindrome 3 | // or false if it is not. Palindromes are strings that 4 | // form the same word if it is reversed. *Do* include spaces 5 | // and punctuation in determining if the string is a palindrome. 6 | // --- Examples: 7 | // palindrome("abba") === true 8 | // palindrome("abcdefg") === false 9 | 10 | function palindrome(str) {} 11 | 12 | module.exports = palindrome; 13 | -------------------------------------------------------------------------------- /exercises/palindrome/test.js: -------------------------------------------------------------------------------- 1 | const palindrome = require('./index'); 2 | 3 | test('palindrome function is defined', () => { 4 | expect(typeof palindrome).toEqual('function'); 5 | }); 6 | 7 | test('"aba" is a palindrome', () => { 8 | expect(palindrome('aba')).toBeTruthy(); 9 | }); 10 | 11 | test('" aba" is not a palindrome', () => { 12 | expect(palindrome(' aba')).toBeFalsy(); 13 | }); 14 | 15 | test('"aba " is not a palindrome', () => { 16 | expect(palindrome('aba ')).toBeFalsy(); 17 | }); 18 | 19 | test('"greetings" is not a palindrome', () => { 20 | expect(palindrome('greetings')).toBeFalsy(); 21 | }); 22 | 23 | test('"1000000001" a palindrome', () => { 24 | expect(palindrome('1000000001')).toBeTruthy(); 25 | }); 26 | 27 | test('"Fish hsif" is not a palindrome', () => { 28 | expect(palindrome('Fish hsif')).toBeFalsy(); 29 | }); 30 | 31 | test('"pennep" a palindrome', () => { 32 | expect(palindrome('pennep')).toBeTruthy(); 33 | }); 34 | -------------------------------------------------------------------------------- /exercises/pyramid/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a positive number N. 3 | // The function should console log a pyramid shape 4 | // with N levels using the # character. Make sure the 5 | // pyramid has spaces on both the left *and* right hand sides 6 | // --- Examples 7 | // pyramid(1) 8 | // '#' 9 | // pyramid(2) 10 | // ' # ' 11 | // '###' 12 | // pyramid(3) 13 | // ' # ' 14 | // ' ### ' 15 | // '#####' 16 | 17 | function pyramid(n) {} 18 | 19 | module.exports = pyramid; 20 | -------------------------------------------------------------------------------- /exercises/pyramid/test.js: -------------------------------------------------------------------------------- 1 | const pyramid = require('./index'); 2 | 3 | beforeEach(() => { 4 | jest.spyOn(console, 'log'); 5 | }); 6 | 7 | afterEach(() => { 8 | console.log.mockRestore(); 9 | }); 10 | 11 | test('pyramid is a function', () => { 12 | expect(typeof pyramid).toEqual('function'); 13 | }); 14 | 15 | test('prints a pryamid for n = 2', () => { 16 | pyramid(2); 17 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 18 | expect(console.log.mock.calls[1][0]).toEqual('###'); 19 | expect(console.log.mock.calls.length).toEqual(2); 20 | }); 21 | 22 | test('prints a pryamid for n = 3', () => { 23 | pyramid(3); 24 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 25 | expect(console.log.mock.calls[1][0]).toEqual(' ### '); 26 | expect(console.log.mock.calls[2][0]).toEqual('#####'); 27 | expect(console.log.mock.calls.length).toEqual(3); 28 | }); 29 | 30 | test('prints a pryamid for n = 4', () => { 31 | pyramid(4); 32 | expect(console.log.mock.calls[0][0]).toEqual(' # '); 33 | expect(console.log.mock.calls[1][0]).toEqual(' ### '); 34 | expect(console.log.mock.calls[2][0]).toEqual(' ##### '); 35 | expect(console.log.mock.calls[3][0]).toEqual('#######'); 36 | expect(console.log.mock.calls.length).toEqual(4); 37 | }); 38 | -------------------------------------------------------------------------------- /exercises/qfroms/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement a Queue datastructure using two stacks. 3 | // *Do not* create an array inside of the 'Queue' class. 4 | // Queue should implement the methods 'add', 'remove', and 'peek'. 5 | // For a reminder on what each method does, look back 6 | // at the Queue exercise. 7 | // --- Examples 8 | // const q = new Queue(); 9 | // q.add(1); 10 | // q.add(2); 11 | // q.peek(); // returns 1 12 | // q.remove(); // returns 1 13 | // q.remove(); // returns 2 14 | 15 | const Stack = require('./stack'); 16 | 17 | class Queue {} 18 | 19 | module.exports = Queue; 20 | -------------------------------------------------------------------------------- /exercises/qfroms/stack.js: -------------------------------------------------------------------------------- 1 | class Stack { 2 | constructor() { 3 | this.data = []; 4 | } 5 | 6 | push(record) { 7 | this.data.push(record); 8 | } 9 | 10 | pop() { 11 | return this.data.pop(); 12 | } 13 | 14 | peek() { 15 | return this.data[this.data.length - 1]; 16 | } 17 | } 18 | 19 | module.exports = Stack; 20 | -------------------------------------------------------------------------------- /exercises/qfroms/test.js: -------------------------------------------------------------------------------- 1 | const Queue = require('./index'); 2 | 3 | test('Queue is a class', () => { 4 | expect(typeof Queue.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('can add elements to a queue', () => { 8 | const q = new Queue(); 9 | expect(() => { 10 | q.add(1); 11 | }).not.toThrow(); 12 | }); 13 | 14 | test('can remove elements from a queue', () => { 15 | const q = new Queue(); 16 | expect(() => { 17 | q.add(1); 18 | q.remove(); 19 | }).not.toThrow(); 20 | }); 21 | 22 | test('Order of elements is maintained', () => { 23 | const q = new Queue(); 24 | q.add(1); 25 | q.add(2); 26 | q.add(3); 27 | expect(q.remove()).toEqual(1); 28 | expect(q.remove()).toEqual(2); 29 | expect(q.remove()).toEqual(3); 30 | expect(q.remove()).toEqual(undefined); 31 | }); 32 | 33 | test('peek returns, but does not remove, the first value', () => { 34 | const q = new Queue(); 35 | q.add(1); 36 | q.add(2); 37 | expect(q.peek()).toEqual(1); 38 | expect(q.peek()).toEqual(1); 39 | expect(q.remove()).toEqual(1); 40 | expect(q.remove()).toEqual(2); 41 | }); 42 | -------------------------------------------------------------------------------- /exercises/queue/index.js: -------------------------------------------------------------------------------- 1 | // --- Description 2 | // Create a queue data structure. The queue 3 | // should be a class with methods 'add' and 'remove'. 4 | // Adding to the queue should store an element until 5 | // it is removed 6 | // --- Examples 7 | // const q = new Queue(); 8 | // q.add(1); 9 | // q.remove(); // returns 1; 10 | 11 | class Queue {} 12 | 13 | module.exports = Queue; 14 | -------------------------------------------------------------------------------- /exercises/queue/test.js: -------------------------------------------------------------------------------- 1 | const Queue = require('./index'); 2 | 3 | test('Queue is a class', () => { 4 | expect(typeof Queue.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('can add elements to a queue', () => { 8 | const q = new Queue(); 9 | expect(() => { 10 | q.add(1); 11 | }).not.toThrow(); 12 | }); 13 | 14 | test('can remove elements from a queue', () => { 15 | const q = new Queue(); 16 | expect(() => { 17 | q.add(1); 18 | q.remove(); 19 | }).not.toThrow(); 20 | }); 21 | 22 | test('Order of elements is maintained', () => { 23 | const q = new Queue(); 24 | q.add(1); 25 | q.add(2); 26 | q.add(3); 27 | expect(q.remove()).toEqual(1); 28 | expect(q.remove()).toEqual(2); 29 | expect(q.remove()).toEqual(3); 30 | expect(q.remove()).toEqual(undefined); 31 | }); 32 | -------------------------------------------------------------------------------- /exercises/reverseint/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given an integer, return an integer that is the reverse 3 | // ordering of numbers. 4 | // --- Examples 5 | // reverseInt(15) === 51 6 | // reverseInt(981) === 189 7 | // reverseInt(500) === 5 8 | // reverseInt(-15) === -51 9 | // reverseInt(-90) === -9 10 | 11 | function reverseInt(n) {} 12 | 13 | module.exports = reverseInt; 14 | -------------------------------------------------------------------------------- /exercises/reverseint/test.js: -------------------------------------------------------------------------------- 1 | const reverseInt = require('./index'); 2 | 3 | test('ReverseInt function exists', () => { 4 | expect(reverseInt).toBeDefined(); 5 | }); 6 | 7 | test('ReverseInt handles 0 as an input', () => { 8 | expect(reverseInt(0)).toEqual(0); 9 | }); 10 | 11 | test('ReverseInt flips a positive number', () => { 12 | expect(reverseInt(5)).toEqual(5); 13 | expect(reverseInt(15)).toEqual(51); 14 | expect(reverseInt(90)).toEqual(9); 15 | expect(reverseInt(2359)).toEqual(9532); 16 | }); 17 | 18 | test('ReverseInt flips a negative number', () => { 19 | expect(reverseInt(-5)).toEqual(-5); 20 | expect(reverseInt(-15)).toEqual(-51); 21 | expect(reverseInt(-90)).toEqual(-9); 22 | expect(reverseInt(-2359)).toEqual(-9532); 23 | }); 24 | -------------------------------------------------------------------------------- /exercises/reversestring/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a string, return a new string with the reversed 3 | // order of characters 4 | // --- Examples 5 | // reverse('apple') === 'leppa' 6 | // reverse('hello') === 'olleh' 7 | // reverse('Greetings!') === '!sgniteerG' 8 | 9 | function reverse(str) {} 10 | 11 | module.exports = reverse; 12 | -------------------------------------------------------------------------------- /exercises/reversestring/test.js: -------------------------------------------------------------------------------- 1 | const reverse = require('./index'); 2 | 3 | test('Reverse function exists', () => { 4 | expect(reverse).toBeDefined(); 5 | }); 6 | 7 | test('Reverse reverses a string', () => { 8 | expect(reverse('abcd')).toEqual('dcba'); 9 | }); 10 | 11 | test('Reverse reverses a string', () => { 12 | expect(reverse(' abcd')).toEqual('dcba '); 13 | }); 14 | -------------------------------------------------------------------------------- /exercises/sorting/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement bubbleSort, selectionSort, and mergeSort 3 | 4 | function bubbleSort(arr) { 5 | 6 | } 7 | 8 | function selectionSort(arr) { 9 | 10 | } 11 | 12 | function mergeSort(arr) { 13 | 14 | } 15 | 16 | function merge(left, right) { 17 | 18 | } 19 | 20 | module.exports = { bubbleSort, selectionSort, mergeSort, merge }; 21 | -------------------------------------------------------------------------------- /exercises/sorting/test.js: -------------------------------------------------------------------------------- 1 | const S = require('./index'); 2 | const bubbleSort = S.bubbleSort; 3 | const selectionSort = S.selectionSort; 4 | const mergeSort = S.mergeSort; 5 | const merge = S.merge; 6 | 7 | function getArray() { 8 | return [100, -40, 500, -124, 0, 21, 7]; 9 | } 10 | 11 | function getSortedArray() { 12 | return [-124, -40, 0, 7, 21, 100, 500]; 13 | } 14 | 15 | describe('Bubble sort', () => { 16 | test('sorts an array', () => { 17 | expect(bubbleSort(getArray())).toEqual(getSortedArray()); 18 | }); 19 | }); 20 | 21 | describe('Selection sort', () => { 22 | test('sorts an array', () => { 23 | expect(selectionSort(getArray())).toEqual(getSortedArray()); 24 | }); 25 | }); 26 | 27 | describe('Merge sort', () => { 28 | test('merge function can join together two sorted arrays', () => { 29 | const left = [1, 10]; 30 | const right = [2, 8, 12]; 31 | 32 | expect(merge(left, right)).toEqual([1,2,8,10,12]); 33 | }); 34 | 35 | test('sorts an array', () => { 36 | expect(mergeSort(getArray())).toEqual(getSortedArray()); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /exercises/stack/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Create a stack data structure. The stack 3 | // should be a class with methods 'push', 'pop', and 4 | // 'peek'. Adding an element to the stack should 5 | // store it until it is removed. 6 | // --- Examples 7 | // const s = new Stack(); 8 | // s.push(1); 9 | // s.push(2); 10 | // s.pop(); // returns 2 11 | // s.pop(); // returns 1 12 | 13 | class Stack {} 14 | 15 | module.exports = Stack; 16 | -------------------------------------------------------------------------------- /exercises/stack/test.js: -------------------------------------------------------------------------------- 1 | const Stack = require('./index'); 2 | 3 | test('Stack is a class', () => { 4 | expect(typeof Stack.prototype.constructor).toEqual('function'); 5 | }); 6 | 7 | test('stack can add and remove items', () => { 8 | const s = new Stack(); 9 | s.push(1); 10 | expect(s.pop()).toEqual(1); 11 | s.push(2); 12 | expect(s.pop()).toEqual(2); 13 | }); 14 | 15 | test('stack can follows first in, last out', () => { 16 | const s = new Stack(); 17 | s.push(1); 18 | s.push(2); 19 | s.push(3); 20 | expect(s.pop()).toEqual(3); 21 | expect(s.pop()).toEqual(2); 22 | expect(s.pop()).toEqual(1); 23 | }); 24 | 25 | test('peek returns the first element but doesnt pop it', () => { 26 | const s = new Stack(); 27 | s.push(1); 28 | s.push(2); 29 | s.push(3); 30 | expect(s.peek()).toEqual(3); 31 | expect(s.pop()).toEqual(3); 32 | expect(s.peek()).toEqual(2); 33 | expect(s.pop()).toEqual(2); 34 | expect(s.peek()).toEqual(1); 35 | expect(s.pop()).toEqual(1); 36 | }); 37 | -------------------------------------------------------------------------------- /exercises/steps/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that accepts a positive number N. 3 | // The function should console log a step shape 4 | // with N levels using the # character. Make sure the 5 | // step has spaces on the right hand side! 6 | // --- Examples 7 | // steps(2) 8 | // '# ' 9 | // '##' 10 | // steps(3) 11 | // '# ' 12 | // '## ' 13 | // '###' 14 | // steps(4) 15 | // '# ' 16 | // '## ' 17 | // '### ' 18 | // '####' 19 | 20 | function steps(n) {} 21 | 22 | module.exports = steps; 23 | -------------------------------------------------------------------------------- /exercises/steps/test.js: -------------------------------------------------------------------------------- 1 | const steps = require('./index'); 2 | 3 | beforeEach(() => { 4 | jest.spyOn(console, 'log'); 5 | }); 6 | 7 | afterEach(() => { 8 | console.log.mockRestore(); 9 | }); 10 | 11 | test('steps is a function', () => { 12 | expect(typeof steps).toEqual('function'); 13 | }); 14 | 15 | test('steps called with n = 1', () => { 16 | steps(1); 17 | expect(console.log.mock.calls[0][0]).toEqual('#'); 18 | expect(console.log.mock.calls.length).toEqual(1); 19 | }); 20 | 21 | test('steps called with n = 2', () => { 22 | steps(2); 23 | expect(console.log.mock.calls[0][0]).toEqual('# '); 24 | expect(console.log.mock.calls[1][0]).toEqual('##'); 25 | expect(console.log.mock.calls.length).toEqual(2); 26 | }); 27 | 28 | test('steps called with n = 3', () => { 29 | steps(3); 30 | expect(console.log.mock.calls[0][0]).toEqual('# '); 31 | expect(console.log.mock.calls[1][0]).toEqual('## '); 32 | expect(console.log.mock.calls[2][0]).toEqual('###'); 33 | expect(console.log.mock.calls.length).toEqual(3); 34 | }); 35 | -------------------------------------------------------------------------------- /exercises/tree/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Create a node class. The constructor 3 | // should accept an argument that gets assigned 4 | // to the data property and initialize an 5 | // empty array for storing children. The node 6 | // class should have methods 'add' and 'remove'. 7 | // 2) Create a tree class. The tree constructor 8 | // should initialize a 'root' property to null. 9 | // 3) Implement 'traverseBF' and 'traverseDF' 10 | // on the tree class. Each method should accept a 11 | // function that gets called with each element in the tree 12 | 13 | class Node {} 14 | 15 | class Tree {} 16 | 17 | module.exports = { Tree, Node }; 18 | -------------------------------------------------------------------------------- /exercises/tree/test.js: -------------------------------------------------------------------------------- 1 | const T = require('./index'); 2 | const Node = T.Node; 3 | const Tree = T.Tree; 4 | 5 | describe('Node', () => { 6 | test('Node is a constructor', () => { 7 | expect(typeof Node.prototype.constructor).toEqual('function'); 8 | }); 9 | 10 | test('Node has a data and children properties', () => { 11 | const n = new Node('a'); 12 | expect(n.data).toEqual('a'); 13 | expect(n.children.length).toEqual(0); 14 | }); 15 | 16 | test('Node can add children', () => { 17 | const n = new Node('a'); 18 | n.add('b'); 19 | expect(n.children.length).toEqual(1); 20 | expect(n.children[0].children).toEqual([]); 21 | }); 22 | 23 | test('Node can remove children', () => { 24 | const n = new Node('a'); 25 | n.add('b'); 26 | expect(n.children.length).toEqual(1); 27 | n.remove('b'); 28 | expect(n.children.length).toEqual(0); 29 | }); 30 | }); 31 | 32 | describe.skip('Tree', () => { 33 | test('starts empty', () => { 34 | const t = new Tree(); 35 | expect(t.root).toEqual(null); 36 | }); 37 | 38 | test('Can traverse bf', () => { 39 | const letters = []; 40 | const t = new Tree(); 41 | t.root = new Node('a'); 42 | t.root.add('b'); 43 | t.root.add('c'); 44 | t.root.children[0].add('d'); 45 | 46 | t.traverseBF(node => { 47 | letters.push(node.data); 48 | }); 49 | 50 | expect(letters).toEqual(['a', 'b', 'c', 'd']); 51 | }); 52 | 53 | test('Can traverse DF', () => { 54 | const letters = []; 55 | const t = new Tree(); 56 | t.root = new Node('a'); 57 | t.root.add('b'); 58 | t.root.add('d'); 59 | t.root.children[0].add('c'); 60 | 61 | t.traverseDF(node => { 62 | letters.push(node.data); 63 | }); 64 | 65 | expect(letters).toEqual(['a', 'b', 'c', 'd']); 66 | }); 67 | }); 68 | -------------------------------------------------------------------------------- /exercises/validate/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Given a node, validate the binary search tree, 3 | // ensuring that every node's left hand child is 4 | // less than the parent node's value, and that 5 | // every node's right hand child is greater than 6 | // the parent 7 | 8 | function validate(node, min = null, max = null) {} 9 | 10 | module.exports = validate; 11 | -------------------------------------------------------------------------------- /exercises/validate/node.js: -------------------------------------------------------------------------------- 1 | class Node { 2 | constructor(data) { 3 | this.data = data; 4 | this.left = null; 5 | this.right = null; 6 | } 7 | 8 | insert(data) { 9 | if (data < this.data && this.left) { 10 | this.left.insert(data); 11 | } else if (data < this.data) { 12 | this.left = new Node(data); 13 | } else if (data > this.data && this.right) { 14 | this.right.insert(data); 15 | } else if (data > this.data) { 16 | this.right = new Node(data); 17 | } 18 | } 19 | } 20 | 21 | module.exports = Node; 22 | -------------------------------------------------------------------------------- /exercises/validate/test.js: -------------------------------------------------------------------------------- 1 | const Node = require('./node'); 2 | const validate = require('./index'); 3 | 4 | test('Validate recognizes a valid BST', () => { 5 | const n = new Node(10); 6 | n.insert(5); 7 | n.insert(15); 8 | n.insert(0); 9 | n.insert(20); 10 | 11 | expect(validate(n)).toEqual(true); 12 | }); 13 | 14 | test('Validate recognizes an invalid BST', () => { 15 | const n = new Node(10); 16 | n.insert(5); 17 | n.insert(15); 18 | n.insert(0); 19 | n.insert(20); 20 | n.left.left.right = new Node(999); 21 | 22 | expect(validate(n)).toEqual(false); 23 | }); 24 | -------------------------------------------------------------------------------- /exercises/vowels/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Write a function that returns the number of vowels 3 | // used in a string. Vowels are the characters 'a', 'e' 4 | // 'i', 'o', and 'u'. 5 | // --- Examples 6 | // vowels('Hi There!') --> 3 7 | // vowels('Why do you ask?') --> 4 8 | // vowels('Why?') --> 0 9 | 10 | function vowels(str) {} 11 | 12 | module.exports = vowels; 13 | -------------------------------------------------------------------------------- /exercises/vowels/test.js: -------------------------------------------------------------------------------- 1 | const vowels = require('./index'); 2 | 3 | test('Vowels is a function', () => { 4 | expect(typeof vowels).toEqual('function'); 5 | }); 6 | 7 | test('returns the number of vowels used', () => { 8 | expect(vowels('aeiou')).toEqual(5); 9 | }); 10 | 11 | test('returns the number of vowels used when they are capitalized', () => { 12 | expect(vowels('AEIOU')).toEqual(5); 13 | }); 14 | 15 | test('returns the number of vowels used', () => { 16 | expect(vowels('abcdefghijklmnopqrstuvwxyz')).toEqual(5); 17 | }); 18 | 19 | test('returns the number of vowels used', () => { 20 | expect(vowels('bcdfghjkl')).toEqual(0); 21 | }); 22 | -------------------------------------------------------------------------------- /exercises/weave/index.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // 1) Complete the task in weave/queue.js 3 | // 2) Implement the 'weave' function. Weave 4 | // receives two queues as arguments and combines the 5 | // contents of each into a new, third queue. 6 | // The third queue should contain the *alterating* content 7 | // of the two queues. The function should handle 8 | // queues of different lengths without inserting 9 | // 'undefined' into the new one. 10 | // *Do not* access the array inside of any queue, only 11 | // use the 'add', 'remove', and 'peek' functions. 12 | // --- Example 13 | // const queueOne = new Queue(); 14 | // queueOne.add(1); 15 | // queueOne.add(2); 16 | // const queueTwo = new Queue(); 17 | // queueTwo.add('Hi'); 18 | // queueTwo.add('There'); 19 | // const q = weave(queueOne, queueTwo); 20 | // q.remove() // 1 21 | // q.remove() // 'Hi' 22 | // q.remove() // 2 23 | // q.remove() // 'There' 24 | 25 | const Queue = require('./queue'); 26 | 27 | function weave(sourceOne, sourceTwo) {} 28 | 29 | module.exports = weave; 30 | -------------------------------------------------------------------------------- /exercises/weave/queue.js: -------------------------------------------------------------------------------- 1 | // --- Directions 2 | // Implement a 'peek' method in this Queue class. 3 | // Peek should return the last element (the next 4 | // one to be returned) from the queue *without* 5 | // removing it. 6 | 7 | class Queue { 8 | constructor() { 9 | this.data = []; 10 | } 11 | 12 | add(record) { 13 | this.data.unshift(record); 14 | } 15 | 16 | remove() { 17 | return this.data.pop(); 18 | } 19 | } 20 | 21 | module.exports = Queue; 22 | -------------------------------------------------------------------------------- /exercises/weave/test.js: -------------------------------------------------------------------------------- 1 | const weave = require('./index'); 2 | const Queue = require('./queue'); 3 | 4 | test('queues have a peek function', () => { 5 | const q = new Queue(); 6 | expect(typeof q.peek).toEqual('function'); 7 | }); 8 | 9 | test('peek returns, but does not remove, the first value', () => { 10 | const q = new Queue(); 11 | q.add(1); 12 | q.add(2); 13 | expect(q.peek()).toEqual(1); 14 | expect(q.peek()).toEqual(1); 15 | expect(q.remove()).toEqual(1); 16 | expect(q.remove()).toEqual(2); 17 | }); 18 | 19 | test('weave is a function', () => { 20 | expect(typeof weave).toEqual('function'); 21 | }); 22 | 23 | test('weave can combine two queues', () => { 24 | const one = new Queue(); 25 | one.add(1); 26 | one.add(2); 27 | one.add(3); 28 | one.add(4); 29 | const two = new Queue(); 30 | two.add('one'); 31 | two.add('two'); 32 | two.add('three'); 33 | two.add('four'); 34 | 35 | const result = weave(one, two); 36 | expect(result.remove()).toEqual(1); 37 | expect(result.remove()).toEqual('one'); 38 | expect(result.remove()).toEqual(2); 39 | expect(result.remove()).toEqual('two'); 40 | expect(result.remove()).toEqual(3); 41 | expect(result.remove()).toEqual('three'); 42 | expect(result.remove()).toEqual(4); 43 | expect(result.remove()).toEqual('four'); 44 | expect(result.remove()).toBeUndefined(); 45 | }); 46 | --------------------------------------------------------------------------------