├── .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 |
Function
16 |
Arguments
17 |
Returns
18 |
Directions
19 |
Example
20 |
21 |
22 |
23 |
24 |
constructor
25 |
(Data, Node)
26 |
Node
27 |
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 |
35 |
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 |
44 |
45 |
46 |
47 |
48 |
LinkedList Class API
49 |
50 |
51 |
52 |
Function
53 |
Arguments
54 |
Returns
55 |
Directions
56 |
Example
57 |
58 |
59 |
60 |
61 |
constructor
62 |
-
63 |
(LinkedList)
64 |
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 |
71 |
72 |
73 | const list = new LinkedList();
74 | list.head // null
75 |
76 |
77 |
78 |
79 |
insertFirst
80 |
(data)
81 |
-
82 |
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 |
87 |
88 |
89 | const list = new LinkedList();
90 | list.insertFirst('Hi There'); // List has one node
91 |
92 |
93 |
94 |
95 |
size
96 |
-
97 |
(integer)
98 |
99 | Returns the number of nodes in the linked list.
100 |
357 | Linked list should be compatible as the subject of a 'for...of' loop
358 |
359 |
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 |
375 |
376 |
377 |
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 | 7ZhNc9owEIZ/jWfIJeMPIORYSFJ66KGlMzmv7cXWRJaoLALpr+9Kli0ch0mHNhw6mBmwXq1ke99nhSBIFtX+s4JN+VXmyIM4zPdBchfEcRQnM/owykujTJKbRigUy12QF1bsFzoxdOqW5Vj3ArWUXLNNX8ykEJjpngZKyV0/bC15/6obKHAgrDLgQ/WR5bp0ahSGvmOJrCjdpWcT15FC9lQouRXuekGcrO3RdFfQzuXi6xJyuTuQkvsgWSgpdXNW7RfITW7btDXjHo70dvetUOg/GRA3A56Bb92jL2RVSUHaSismCjr5tsVaMylqd8v6pU2TfVA0U4VBMt+VTONqA5np3REYpJW64tSK6LR7VBPLIUU+75K1kFwq6hJSoAnVSj5hK1IOw5l5dT2tJ5Su+ZpxfhDpsk26FNqBFYeufTijPUgHzgpBWkYZQ+qcu4yg0rg/mtWo84pqAGWFWr1QSDvgxtnr8L91zZ1nKW5RKg8wmjoNHL5FN7O3kE6ci287Oh44eieplKiASjSVxZ5RWBeduyU8Gx2EuX+FGwRNjlJplaAgo5SYscwMYXSXD/81AxzX+t8QEL8iYDwZIjAdfxACkwECjyVoE+A5qGSt7QLqqr2zu3W7CXOYXHw/0fckOaPv02Ol3xX7J1/wzl+o8HWxQ28IZSUcWXCYtuuEfYNCQXV14eJkLt74SvgwLmYDLr74haAzGuwDcSZyJS0UI9qDCc1oV2S3X5aAGvnanKxbHiwZCik5NeYXIE4GomufA4jbARDfGwcdBoNNwiiIpz+3ZlM6X9JU0jfNnhfpW8SuM16WnOPSN68uVJxERXTObUP74+tNLJrFQqrc7hCkqf8dtbrNIRzDhVH7R4kK32XGRYVmyAWcv1xOonOCEw3AoV+RZIrugXFNtkJlHBJpvWk48E6naZplQEf+LihpksUwziOvXF8wOQmTyQdiQk3/P4btO/izKLn/DQ==7Zldb9owFIZ/yy6itjcoH5DC5WDtJk3btLFq18Y5JC7Gzhyngf36HSdOgAWqKipMqkIliF9/JD7POfZx6gSz9eajImnyRUbAHd+NNk7wwfH9iefhtxG2lTAM3EqIFYsqydsJc/YHrFg3y1kE2UFDLSXXLD0UqRQCqD7QiFKyOGy2lPzwrimJoSXMKeFt9ReLdGJVz3V3FZ+AxYm99XhkKxaErmIlc2Hv5/jBsvxU1WtSj2XbZwmJZLEnBXdOMFNS6upqvZkBN6atzVb1uz9R2zy3AqFf0mFYdXgiPLdTn2vFRIza9xwyzaTAy5/G7tXz6m1to3KWYMZxnWBaJEzDPCXU1BboFKgles2x5OFlM0/TlpMF8GljqZnkUmGVkAJMU63kCmoRDeiOzV9TUwNBW02XjPO9ltbUqEuhrVf5ri3vj1h+UCecxQI1iuYCrJxac4DSsDlpUq8Bhf4Pcg1abbGJ7eDXTrI99Oli50j+2GrJng+FViPWd+Nm5B0/vLAIj+MMWzi/AiIy0YNfCnBiGZh7lChL0MH9/yM79hdBGL6EbDSCcTTsQJbDUr8SV/+QazBsgw3dM4G9bYF9qEAqRcwz4oCJjLJyrVOmH7ozsdF7jdIdoYnjz8olKL0Z4O/7J8misixywpuOXMo0e/emg/31XCII/gn1UdslhpMzucS45RLT0iMKfHz8lUsD2bjHIFVSS71NYWBXgOubHnAnwMPwgoAnJ2K+2qH3qGYpZ9owdYmIjlB/lEz0yLsidy+IvM4Vng1qAUUN+VrcNCs3VYArfpm6wTrV23p3eNuZ2/nA+7eXBO+dytxMqpYL9jsHAZnZ4GkCdGV8oYSOGCx0mhBFKO77We0oRJjprZg5jPRZXrcsb3RkSz9bluf5LS/4AVQq4wcctDmiWOSGMRMlY0N78WhOwX2cd4nz8MgB7XxxHpyK8/KERuUaAWlTTGB3RvNdRCN2yM1sCsz7+6juGNXh5JJR3X7JUiVy7ew8ymmfnHcN5NtLnr680bOBXJ2/oQxktHycOP1Ll9cI3IvGbftt2kNWLccG5RWm3YPBQC6vnOq1ielq9uVvnwd9BHdLuc+4FWNx91q9rNv710Vw9xc=7VnLcpswFP0aZpJNhodxyDJ2kqaLLlp3JmsB16CJkFwhx3a/vlcgwBhcp34tOuAZWzqSeNxzjnSRLW+arb9Iski/iRiY5drx2vKeLNd1XC/AH41sSsT37ksgkTQ2nRpgRn+DAW2DLmkMeaujEoIpumiDkeAcItXCiJRi1e42F6x91QVJoAPMIsK66BuNVWpQx7abhlegSWouHfimISTReyLFkpvrWa43L46yOSPVuUz/PCWxWG1B3rPlTaUQqixl6ykwHdsqbOW4lz2t9X1L4OozA9xywAdhS/PoU5FlgiM2U5LyBAvfl5ArKnhublltqjAVDwr6VLblTVYpVTBbkEi3rlAYiKUqY1hzsFg/qu7LSAhsUgdrKpiQ2MQFB91VSfEOFYgxtAP9qVsqTjBckzllbKuniTbigisjLNc29e0zFgfihNGEIxZhxAAbJyYiIBWs90bVqblCD4DIQMkNdjEDAsPuplK1qa8aLbkVlm7JaGwwYuSb1GduKMSCYbGfUa/D6JNAK6GBUtDOoh/ACxYNuyn50Djh+v4lLIAoZBStlRJJIgyJHkv1EIp3+fJfa4DBXJ1HAc6OBEbjrgTGowtJYNSRwFtKlO7Q6CATuSomUOP2mu6K7bKbkcnA+5G8e6Mr8u7vs35t9sfG8IZfksGu2UlrCEbFvimEQ1UxTxRfJJEkux10cfR80LMkXEwX444uvjYTQU00KR6IUR5LUYjiBnMwrihmRUX6VSggBzbXhXmlh0IZEjA4OcSDII4WRJ0zXEMQ9x1B/CgZNDLoJAk3ljv+tdRJ6eQVTyWaqs55AVeRYp5pYMEYvDbV20EVR6nCuWbaEPxFFeVcIWRcJAhC23+FtTo3JPvUQrH+MwUJByVjetl6yKCbE2cT94q6eejoBt8hkRPV0sUdskoyTRAP80Upg4boMAyjiOARH9RJ6EUuGcVOg9wNKjlKJf41VVJt7WzJpEMbMrHQxWgp2WaCGek7qMP8NWSfymbght54/Bk2Yx+CeHQ8m1IoovdU9E0H9pl2HbzDi0fQw24ti5PodQ7kFNXqsEM5Pq7aseNeVvZxsBNbHUSdtT4aOKNxrC/Xq6P2TPEP4vks8Wcg9sHZnd39DrHOfQ+z/jmI7W4RDr69qG/79gwu59vufuEUQ652NgUG157s2pF9Tdd23/kH117UtX3JVJ9rz5JLdV/gpwJZ4cNqe37f+hdcbbHa/NdXtG39oeo9/wE=7VZNb9swDP01BrabP9IuOS5uu112GHLombUZS6gsBooSJ/v1o2zajusFKIp1h6E2YEiPpGy99yg4yvL69M3BTv2gEk2UxuUpyu6iNF2tYn4G4NwBi0yAyumyg5IR2OhfKGCfdtAl7ieJnsh4vZuCBVmLhZ9g4Bw107Qtmelbd1DhDNgUYObooy69EjSJ4zHwHXWl5NXLGwk8QfFcOTpYeV+UZtv26sI19GtJ/l5BSc0FlN1HWe6IfDeqTzmaQG1PW1f3cCU6fLdD619TkHYFRzAH2XpOdU2WsY132lY8+HnAvddk9/LJ/tzT1G4Uw1JxlK0bpT1udlCEaMO+YEz52vAs4eGw1ZBr4AnNeiArJ0OOQ5YshlTv6Bl7kDmMl+EeIr0mTNd6q425yBS2GSfrxVhpLPPLFduLcTC6sowVzBhycC2MoPN4uspqMmjFLYBUo3dnTukLliLveTBON29GM6W9l9SFj24FA/FvNSw9asgDkfHPkmYzSe+Ie4k7SGFoLX1E28oo8io4Bhxs2IDDHYJnSbm3FDgomJNQq0OJ5q98+K9NYHDr/44F0hcWSFdzC9wu3skCi5kFHhX4kDD6oKa9b09QafdB7l7tLk1s8qH7G3VPvvxD3W+utf7Q7F/Hhhd9ocaXzQ6TEmYl/tQaR/v2nGgfUDmoP3/44s3nQfZ+vuDp+AfRxi7+0rL73w==3VdLc5swEP4tOXBsR0ax42vsJPWhPaUzbY8yrEG1YKmQX/31lWDFI5CMM20eUzzG0refVqv9VlgEfJkdP2lRpF8wBhWELD4G/CYIw3k4tXcHnGqAT+c1kGgZ19CkBe7lbyCQEbqTMZQ9okFURhZ9MMI8h8j0MKE1Hvq0Dar+rIVIYADcR0IN0W8yNimhE8ZawwpkktLU8ykZ1iLaJhp3Oc0XhHxTXbU5E94X8ctUxHjoQPw24EuNaOpWdlyCcqn1aavH3T1ibeLWkJtzBpBOpTn5pUNsM0Fd1CbFBHOhblt0US0PnANme6nJlG1ObBOO0nzvtH84ysep7ZVGaHPthLFQjjl47E4qRY4gjz0jUqIsZVSDRHFOf4IxJ6oWsTNooTbEz4gF8UqjcQtLVKirRXFWXY3Fa8otssHckMuQUX9sZJ0ol51HU01QiTsdESuk4hU6AWLxRma7ewAzMPpkKRqUMHLf9y6ojpOG12ppGyTnuLQ09V6oHfhinP3aucparCwVrfFrChouWnxQDX2tD6k0cF+IanUHu/P7+jfF7LhKrEEtmu3gU9qI/1ChufsMFAqdIrYAOkzaT+crJ5RMcldVVijQzSr3oA0cnxZzKJMfcEkbmB5wzU46tI+L0HPSzpNixv5eWT6mrHL6rRVGW6cl9GT08ma2DKVNxbW1ss73khXHIKyrnK1Rxy5NjlSp5Q2FiGOZJzTcjWjLZpZUv1euKTJXF/m6LGpTFVks96MhWQnMB1LI+VWwMSOOB17ZquIPYCvb0s9p81hN2/h4mUhgPJKHEH/9yNR5kVkofP3g8Lzg3kDQLqnbqby8QTzmbBnfILj03cqo33PaLp4T3AtGdnXztHuLdv9UvPE/PiZUifonh4TLWf+QMGEjh4TJyCGBs+efEmy3fW2obJ1XM377Bw==7ZZNj5swEIZ/DcqV4N1tcg3dtlqpl6ZSz16YYGuNJzJDSfrrOwabD9GVqq26p4CE7HfGNn6fMUki8vry2cmz+oolmCRLy0siPiZZtt+n/PTCdRDuRBAqp8tB2k7CUf+CIMa0VpfQLBIJ0ZA+L8UCrYWCFpp0Drtl2gnNctWzrGAlHAtp1uoPXZIK6jZNp8AX0JUKS+/uQ+BZFi+Vw9aG9ZJMnPprCNcyzhXyGyVL7GaSeExE7hBpaNWXHIy3Nto2jPv0SnR8bweW/mZANgz4KU0btv69dZaVTUNu4xMtoTfVDs7Ka3hvukav+t2Cny9NxKFTmuB4loWPdlwcrCmqDfe23Bz363ONfAZzGB3L0aDjkEULPpUcvkAU2ch05+8xEsGwZ4eTNmaWGSxnHS2F6srS0J/P2F+sS6Mry5qBE9t2CKaAI7i8aux2xMWnALAGcmxOGgaIeASusbJDv5vqScQqULNSegiaDCVcjVNPGLkRSP6ZqlhRzWWfsHHAu2rAk+VZFZbcQM+WFNwI/xvh/TsSvlsRfkK94th/jmaHuMfqtK1uiN+EONu9I+L7FeJvQMPHeYDsoGkN3VC+CaX48P9Qcnf6Be9js39J4vE37VZNj9owEP010d6qEG+AHgvLtof2Uiq1PQ7JkLgYG5nhq7++48TOx4atttq2J0BC8Zvx13tvJkRivj2/t7ArP5kcVZTE+TkSD1GSTNK3/OuASw2IdFoDhZV5DY1aYCl/ogdjjx5kjvteIhmjSO76YGa0xox6GFhrTv20tVH9XXdQ4ABYZqCG6FeZU+nRURy3gQ8oi9JvPU19YAXZprDmoP1+USLW1acObyGs5fP3JeTm1IHEIhJzawzVT9vzHJWjNtBWz3t8Jtqc26Kml0wQ9YQjqIO/+tpYBhCy0vFbgoWM0EFSOxVKdOtbc2SBcncBslIX/jJ0CQRWFKDbJI7E7FRKwuUOMhc9sWMYK2mreDTix4YEl6tghWrW0Dg3ig8kHrTR6FLJmg0GkNmNp+7bRIJaTORsLZXqZHodGDeavOWS2I+7K1YfxkHJQjOmcM1czjxTaAnPz7I9ajTk0kCzRbIXTvETxDitp/iySIKfTq3JxMRjZcdfY4+B93XRLN1qyw9e3utS3w+k/gIbbDTtSg3aSQu5+5VUFV+TFyVj5eiQ/FBQRTxYCigfoglwsmHfx3cWmbU95nc3m7zIJvehDQabjK/YJEn/jU3SgU3mFoGwsoXrDNsdXTqFH3PXVFUruOn8ynYwGv3HdjAeiIQ5vwP90FgqTWE0qEWLzvoydiTDs6RvDn4zSf3wewhpPlg35sYhWPWOd+6F3dWUsUfpDl5tgzoPGZmC/V5mNehT3DI/kOjiNYQDNysxay/w0Zhds91TuwRx+3YRf2CLmkbH3e9dwFSbg82wV2V81QKpAw29YlEByWN/9dcIPxkU+Gekg23f7kewElYKbyX9+pIW11r3XyppHrZ/FKtY58+4WPwC7VZNb9NAEP01VttL5Y84cY8ktHAACakH4LhZT+ylG49Zj0nCr2fXHn81aZUCUjmQQ+R982a9fu95ZC9abffvjCjzj5iC9kI/3XvRWy8Mb4LA/jvg0AKzyG+BzKi0hYIBuFc/gcGOVqsUqgmREDWpcgpKLAqQNMGEMbib0jaop3ctRQZHwL0U+hj9rFLKGQ18fyi8B5XlfOsk5sJayIfMYF3w/bww2jS/trwV3V7Mr3KR4m4ERbdetDKI1F5t9yvQTtpOtrbv7olqf24DBZ3TMGsbfghdQ3fi5lx06LRongYc3/ei5S5XBPelkK66s+ZbLKettqvAXvbP47harEEve0VWqNHYUoEFOCoZfIAOtELNZQLrTV/phLeaLDdK6xEzFZBspMOxIE5PuOD1iOc3P4sLrbLCYho2VpYlPzQYgv2TwgW9HTblgFsgc7AUbpgv2EFOeBiwlLtRXm5423wUlRn3CY5o1m892GQv2KnTrs2PTILU5peXaCjHDAuhbwd0ObVxZBnsFX1x8HXMq69MslKYw6jkll2tImHojXvVxo5a7E65Y3N/2jGkFlWlZAsyxd38GxAd2EFRE1poOP4HxLLL1eOw9NZOwxK9IBStiE655zNghcbaSGZFPI6EyYBZ8emkGNCC1I/p7qdsb1qtUuIwIpSoCqpGO39ywBDA5GYawCB+9KY/4s8Wz/LtRXuCIYD9o5yVyegfmiRJuI7m87MmSQxJOnvVSZKcMUm6ofG3B0n837TfM20Wv55p4ZFpBqg2ReObua5Krejy4uLq2kBaS7i8FFJ64cp9LuXCCElgruyiaZ2LrbMwa2UZCK4eOqTvtdzvNTJvvOAtinVV9sUJdNVLPoqVlZ6m2XnZ2P4j94Ij9/wj9xaLE/YtXm6fXQ6fc+1cHT6Zo9tf7ZZPb6MwEMU/DWp7WYEdEq5Ltt1e9pTDnl2YgFWDI8cpYT/9jmH4F1KJSpF6SSIl+L0xxu83CXh8W5x/G3HI/+gUlMf89OzxXx5jEQvx0wl1K/AwaoXMyLSVgkHYyX9Aok/qSaZwnBRarZWVh6mY6LKExE40YYyupmV7raarHkQGM2GXCDVX/8rU5qQGvj8YryCznJaOQjLeRPKeGX0qaT2P8X3zau1CdOei+mMuUl2NJP7s8a3R2rZHxXkLykXbxdbOe/nE7a/bQGmXTGDthA+hTjC9MFt3YTTbATfB93hc5dLC7iAS51ZIH7XcFgpHAR72G3K1SryBivtItlppg1apS3Cl1uh36ERMyo/cu3e65DGUeC+VGlVSpqjr0lL7sA2Nx2dsXqgLJbMSNQV7zCWmXYOxcP40uaDngW0OugBraiyhCazrBWrxgNO4GhpmQ1I+apU1aYJaNOvPPGDCAyJ1nRqfUQvu2BZi23wfttUc2+qObRE2vvo+bOEMmzzi+AFwR/VD77h7GQgLxt2sclHiV+jxlxlgDMFeUJygIV5jBiR1sSYYGi7DYxepxLvWTzIKmaZumattM22sL3TOUuo3wLy6xBzOMfPoCmd2A87rGWd8lBD1j4bz4yPqT2g3zloULtKs7W43xTmXcvjUp3Lnv+zfmYcT/uzKz5yHt+GPw+E5q/FGz7L8+T8=7ZfLboMwEEW/hj3YkLJt0temqyy6dmACVgyOXKck/fqOw/AqqZRGVdlApMi+M7bxPcPL46vi+GzEPn/VKSiP+enR4w8eYzGL8N8Jp1rgUVwLmZFpLQWdsJafQKJP6kGm8D5ItForK/dDMdFlCYkdaMIYXQ3TtloNV92LDEbCOhFqrL7J1OakBr7fBV5AZjktHUcU2Ihklxl9KGk9j/Ht+ajDhWjmovz3XKS66kn80eMro7WtW8VxBcpZ29hWj3v6Idqet4HSXjOA1QM+hDrQ1gWdmD01Zpy3A26A7/FllUsL671IXLRC+qjltlDYC7DZbsjlKrEBtWwtWWmlDYZKXYJLtUbvoBHRKT92vzbSOI+mLLdSqV4meYq6Li2VD7ujfn/G84G6UDIrUUvQF8DgkvYNxsLxR++ClggWOugCrDlhCg3gTTVQkQdNEVRdySxIynvF0miCijRrZ+5AYYNYXebGR9w2M7druS2m4xaOuCUztyu5hWw6btF8vd3OLZ6O22J+vt3MLQqn4xaMb5T+CBxuzX6jM7CcOPS9JWlklzNK4vvfPQUKmaZumYvlMCyYX1TEtTT/4iEXDOG1/vXghRfgsb+AN75bhjO831x50b/Bw273tXGO9b7o+OMX
--------------------------------------------------------------------------------
/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 |
Function
16 |
Arguments
17 |
Returns
18 |
Directions
19 |
Example
20 |
21 |
22 |
23 |
24 |
Node.constructor
25 |
(Data, Node)
26 |
Node
27 |
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 |
35 |
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 |
44 |
45 |
46 |
47 |
48 |
LinkedList Class API
49 |
50 |
51 |
52 |
Function
53 |
Arguments
54 |
Returns
55 |
Directions
56 |
Example
57 |
58 |
59 |
60 |
61 |
constructor
62 |
-
63 |
(LinkedList)
64 |
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 |
71 |
72 |
73 | const list = new LinkedList();
74 | list.head // null
75 |
76 |
77 |
78 |
79 |
insertFirst
80 |
(data)
81 |
-
82 |
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 |
87 |
88 |
89 | const list = new LinkedList();
90 | list.insertFirst('Hi There'); // List has one node
91 |
92 |
93 |
94 |
95 |
size
96 |
-
97 |
(integer)
98 |
99 | Returns the number of nodes in the linked list.
100 |