diff --git a/AlgoCasts b/AlgoCasts deleted file mode 160000 index 7d6ff43..0000000 --- a/AlgoCasts +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7d6ff439f752c868a341ad0b8360084a88540549 diff --git a/AlgoCasts_3 b/AlgoCasts_3 deleted file mode 160000 index feeab87..0000000 --- a/AlgoCasts_3 +++ /dev/null @@ -1 +0,0 @@ -Subproject commit feeab87936c294d647721184753b164bbf9f46d6 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/.gitignore b/Grider-Stephen-AlgoCasts-JS-Practice/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/index.js new file mode 100644 index 0000000..1a1b598 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/index.js @@ -0,0 +1,51 @@ +// --- Directions +// Check to see if two provided strings are anagrams of eachother. +// One string is an anagram of another if it uses the same characters +// in the same quantity. Only consider characters, not spaces +// or punctuation. Consider capital letters to be the same as lower case +// --- Examples +// anagrams('rail safety', 'fairy tales') --> True +// anagrams('RAIL! SAFETY!', 'fairy tales') --> True +// anagrams('Hi there', 'Bye there') --> False + +function anagrams(stringA, stringB) { + return cleanString(stringA) === cleanString(stringB); +} + +function cleanString(str) { + return str + .replace(/[^\w]/g, '') + .toLowerCase() + .split('') + .sort() + .join(''); +} + +module.exports = anagrams; + +// function anagrams(stringA, stringB) { +// const aCharMap = buildCharMap(stringA); +// const bCharMap = buildCharMap(stringB); +// +// if (Object.keys(aCharMap).length !== Object.keys(bCharMap).length) { +// return false; +// } +// +// for (let char in aCharMap) { +// if (aCharMap[char] !== bCharMap[char]) { +// return false; +// } +// } +// +// return true; +// } +// +// function buildCharMap(str) { +// const charMap = {}; +// +// for (let char of str.replace(/[^\w]/g, '').toLowerCase()) { +// charMap[char] = charMap[char] + 1 || 1; +// } +// +// return charMap; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/test.js new file mode 100644 index 0000000..60f117b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/anagrams/test.js @@ -0,0 +1,27 @@ +const anagrams = require('./index.js'); + +test('anagrams function exists', () => { + expect(typeof anagrams).toEqual('function'); +}); + +test('"hello" is an anagram of "llohe"', () => { + expect(anagrams('hello', 'llohe')).toBeTruthy(); +}); + +test('"Whoa! Hi!" is an anagram of "Hi! Whoa!"', () => { + expect(anagrams('Whoa! Hi!', 'Hi! Whoa!')).toBeTruthy(); +}); + +test('"One One" is not an anagram of "Two two two"', () => { + expect(anagrams('One One', 'Two two two')).toBeFalsy(); +}); + +test('"One one" is not an anagram of "One one c"', () => { + expect(anagrams('One one', 'One one c')).toBeFalsy(); +}); + +test('"A tree, a life, a bench" is not an anagram of "A tree, a fence, a yard"', () => { + expect( + anagrams('A tree, a life, a bench', 'A tree, a fence, a yard') + ).toBeFalsy(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/index.js new file mode 100644 index 0000000..673fd7d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/index.js @@ -0,0 +1,49 @@ +// --- Directions +// 1) Implement the Node class to create +// a binary search tree. The constructor +// should initialize values 'data', 'left', +// and 'right'. +// 2) Implement the 'insert' method for the +// Node class. Insert should accept an argument +// 'data', then create an insert a new node +// at the appropriate location in the tree. +// 3) Implement the 'contains' method for the Node +// class. Contains should accept a 'data' argument +// and return the Node in the tree with the same value. +// If the value isn't in the tree return null. + +class Node { + constructor(data) { + this.data = data; + this.left = null; + this.right = null; + } + + insert(data) { + if (data < this.data && this.left) { + this.left.insert(data); + } else if (data < this.data) { + this.left = new Node(data); + } else if (data > this.data && this.right) { + this.right.insert(data); + } else if (data > this.data) { + this.right = new Node(data); + } + } + + contains(data) { + if (this.data === data) { + return this; + } + + if (this.data < data && this.right) { + return this.right.contains(data); + } else if (this.data > data && this.left) { + return this.left.contains(data); + } + + return null; + } +} + +module.exports = Node; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/test.js new file mode 100644 index 0000000..331ae22 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/bst/test.js @@ -0,0 +1,41 @@ +const Node = require('./index'); + +test('Node is a constructor', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); +}); + +test('Node can insert correctly', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(17); + + expect(node.left.data).toEqual(5); + expect(node.right.data).toEqual(15); + expect(node.right.right.data).toEqual(17); +}); + +test('Contains returns node with the same data', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(20); + node.insert(0); + node.insert(-5); + node.insert(3); + + const three = node.left.left.right; + expect(node.contains(3)).toEqual(three); +}); + +test('Contains returns null if value not found', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(20); + node.insert(0); + node.insert(-5); + node.insert(3); + + expect(node.contains(9999)).toEqual(null); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/index.js new file mode 100644 index 0000000..353993f --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/index.js @@ -0,0 +1,34 @@ +// --- Directions +// Write a function that accepts a string. The function should +// capitalize the first letter of each word in the string then +// return the capitalized string. +// --- Examples +// capitalize('a short sentence') --> 'A Short Sentence' +// capitalize('a lazy fox') --> 'A Lazy Fox' +// capitalize('look, it is working!') --> 'Look, It Is Working!' + +function capitalize(str) { + let result = str[0].toUpperCase(); + + for (let i = 1; i < str.length; i++) { + if (str[i - 1] === ' ') { + result += str[i].toUpperCase(); + } else { + result += str[i]; + } + } + + return result; +} + +module.exports = capitalize; + +// function capitalize(str) { +// const words = []; +// +// for (let word of str.split(' ')) { +// words.push(word[0].toUpperCase() + word.slice(1)); +// } +// +// return words.join(' '); +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/test.js new file mode 100644 index 0000000..21a2423 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/capitalize/test.js @@ -0,0 +1,17 @@ +const capitalize = require('./index'); + +test('Capitalize is a function', () => { + expect(typeof capitalize).toEqual('function'); +}); + +test('capitalizes the first letter of every word in a sentence', () => { + expect(capitalize('hi there, how is it going?')).toEqual( + 'Hi There, How Is It Going?' + ); +}); + +test('capitalizes the first letter', () => { + expect(capitalize('i love breakfast at bill miller bbq')).toEqual( + 'I Love Breakfast At Bill Miller Bbq' + ); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/index.js new file mode 100644 index 0000000..02c9bbb --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/index.js @@ -0,0 +1,39 @@ +// --- Directions +// Given an array and chunk size, divide the array into many subarrays +// where each subarray is of length size +// --- Examples +// chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]] +// chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]] +// chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]] +// chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]] +// chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]] + +function chunk(array, size) { + const chunked = []; + let index = 0; + + while (index < array.length) { + chunked.push(array.slice(index, index + size)); + index += size; + } + + return chunked; +} + +module.exports = chunk; + +// function chunk(array, size) { +// const chunked = []; +// +// for (let element of array) { +// const last = chunked[chunked.length - 1]; +// +// if (!last || last.length === size) { +// chunked.push([element]); +// } else { +// last.push(element); +// } +// } +// +// return chunked; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/test.js new file mode 100644 index 0000000..ef3d645 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/chunk/test.js @@ -0,0 +1,33 @@ +const chunk = require('./index'); + +test('function chunk exists', () => { + expect(typeof chunk).toEqual('function'); +}); + +test('chunk divides an array of 10 elements with chunk size 2', () => { + const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + const chunked = chunk(arr, 2); + + expect(chunked).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]); +}); + +test('chunk divides an array of 3 elements with chunk size 1', () => { + const arr = [1, 2, 3]; + const chunked = chunk(arr, 1); + + expect(chunked).toEqual([[1], [2], [3]]); +}); + +test('chunk divides an array of 5 elements with chunk size 3', () => { + const arr = [1, 2, 3, 4, 5]; + const chunked = chunk(arr, 3); + + expect(chunked).toEqual([[1, 2, 3], [4, 5]]); +}); + +test('chunk divides an array of 13 elements with chunk size 5', () => { + const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + const chunked = chunk(arr, 5); + + expect(chunked).toEqual([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/index.js new file mode 100644 index 0000000..508b09f --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Given a linked list, return true if the list +// is circular, false if it is not. +// --- Examples +// const l = new List(); +// const a = new Node('a'); +// const b = new Node('b'); +// const c = new Node('c'); +// l.head = a; +// a.next = b; +// b.next = c; +// c.next = b; +// circular(l) // true + +function circular(list) { + let slow = list.getFirst(); + let fast = list.getFirst(); + + while (fast.next && fast.next.next) { + slow = slow.next; + fast = fast.next.next; + + if (slow === fast) { + return true; + } + } + + return false; +} + +module.exports = circular; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/linkedlist.js new file mode 100644 index 0000000..b7da56b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/linkedlist.js @@ -0,0 +1,178 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor(values = []) { + this.head = null; + + for (let value of values) { + this.insertLast(value); + } + } + + clear() { + this.head = null; + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getAt(index) { + if (!this.head) { + return null; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + node = node.next; + counter++; + } + return null; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + let counter = 1; + let previous = this.head; + let node = this.head.next; + while (node) { + if (counter === index) { + previous.next = new Node(data, node); + return; + } + previous = node; + node = node.next; + counter++; + } + + previous.next = new Node(data, node); + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index - 1) { + if (node.next) { + return (node.next = node.next.next); + } else { + return (node.next = null); + } + } + node = node.next; + counter++; + } + } + + getFirst() { + return this.head; + } + + insertFirst(data) { + this.head = new Node(data, this.getFirst()); + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node.next) { + node = node.next; + } + + return node; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + last.next = new Node(data); + return last.next; + } else { + this.head = new Node(data); + return this.head; + } + } + + forEach(fn) { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + fn(node); + node = node.next; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/test.js new file mode 100644 index 0000000..99c21fe --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/circular/test.js @@ -0,0 +1,50 @@ +const circular = require('./index'); +const L = require('./linkedlist'); +const List = L.LinkedList; +const Node = L.Node; + +test('circular function is defined', () => { + expect(typeof circular).toEqual('function'); +}); + +test('circular detects circular linked lists', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = b; + + expect(circular(l)).toEqual(true); +}); + +test('circular detects circular linked lists linked at the head', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = a; + + expect(circular(l)).toEqual(true); +}); + +test('circular detects non-circular linked lists', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = null; + + expect(circular(l)).toEqual(false); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/example.html b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/example.html new file mode 100644 index 0000000..c1a8303 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/example.html @@ -0,0 +1,19 @@ + + + + +

Click the button

+ + + diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/index.js new file mode 100644 index 0000000..ee5a600 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/index.js @@ -0,0 +1,37 @@ +// --- Directions +// Create an 'eventing' library out of the +// Events class. The Events class should +// have methods 'on', 'trigger', and 'off'. + +class Events { + constructor() { + this.events = {}; + } + + // Register an event handler + on(eventName, callback) { + if (this.events[eventName]) { + this.events[eventName].push(callback); + } else { + this.events[eventName] = [callback]; + } + } + + // Trigger all callbacks associated + // with a given eventName + trigger(eventName) { + if (this.events[eventName]) { + for (let cb of this.events[eventName]) { + cb(); + } + } + } + + // Remove all event handlers associated + // with the given eventName + off(eventName) { + delete this.events[eventName]; + } +} + +module.exports = Events; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/test.js new file mode 100644 index 0000000..e015819 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/events/test.js @@ -0,0 +1,77 @@ +const Events = require('./index'); + +test('Events can be registered then triggered', () => { + const events = new Events(); + + const cb1 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(1); +}); + +test('Multiple events can be registered then triggered', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.on('click', cb2); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(1); + expect(cb2.mock.calls.length).toBe(1); +}); + +test('Events can be triggered multiple times', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + events.on('click', cb2); + events.trigger('click'); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(3); + expect(cb2.mock.calls.length).toBe(2); +}); + +test('Events can have different names', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + events.on('hover', cb2); + events.trigger('click'); + events.trigger('hover'); + + expect(cb1.mock.calls.length).toBe(2); + expect(cb2.mock.calls.length).toBe(1); +}); + +test('Events can be toggled off', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('hover', cb2); + + events.on('click', cb1); + events.trigger('click'); + events.off('click'); + events.trigger('click'); + + events.trigger('hover'); + + expect(cb1.mock.calls.length).toBe(1); + expect(cb2.mock.calls.length).toBe(1); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/index.js new file mode 100644 index 0000000..51e2ae1 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/index.js @@ -0,0 +1,48 @@ +// --- Directions +// Print out the n-th entry in the fibonacci series. +// The fibonacci series is an ordering of numbers where +// each number is the sum of the preceeding two. +// For example, the sequence +// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] +// forms the first ten entries of the fibonacci series. +// Example: +// fib(4) === 3 + +function memoize(fn) { + const cache = {}; + return function(...args) { + if (cache[args]) { + return cache[args]; + } + + const result = fn.apply(this, args); + cache[args] = result; + + return result; + }; +} + +function slowFib(n) { + if (n < 2) { + return n; + } + + return fib(n - 1) + fib(n - 2); +} + +const fib = memoize(slowFib); + +module.exports = fib; + +// function fib(n) { +// const result = [0, 1]; +// +// for (let i = 2; i <= n; i++) { +// const a = result[i - 1]; +// const b = result[i - 2]; +// +// result.push(a + b); +// } +// +// return result[n]; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/test.js new file mode 100644 index 0000000..02a385d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fib/test.js @@ -0,0 +1,25 @@ +const fib = require('./index'); + +test('Fib function is defined', () => { + expect(typeof fib).toEqual('function'); +}); + +test('calculates correct fib value for 1', () => { + expect(fib(1)).toEqual(1); +}); + +test('calculates correct fib value for 2', () => { + expect(fib(2)).toEqual(1); +}); + +test('calculates correct fib value for 3', () => { + expect(fib(3)).toEqual(2); +}); + +test('calculates correct fib value for 4', () => { + expect(fib(4)).toEqual(3); +}); + +test('calculates correct fib value for 15', () => { + expect(fib(39)).toEqual(63245986); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/index.js new file mode 100644 index 0000000..8fe64c4 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Write a program that console logs the numbers +// from 1 to n. But for multiples of three print +// “fizz” instead of the number and for the multiples +// of five print “buzz”. For numbers which are multiples +// of both three and five print “fizzbuzz”. +// --- Example +// fizzBuzz(5); +// 1 +// 2 +// fizz +// 4 +// buzz + +function fizzBuzz(n) { + for (let i = 1; i <= n; i++) { + // Is the number a multiple of 3 and 5? + if (i % 3 === 0 && i % 5 === 0) { + console.log('fizzbuzz'); + } else if (i % 3 === 0) { + // Is the number a multiple of 3? + console.log('fizz'); + } else if (i % 5 === 0) { + console.log('buzz'); + } else { + console.log(i); + } + } +} + +module.exports = fizzBuzz; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/test.js new file mode 100644 index 0000000..fa5108e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fizzbuzz/test.js @@ -0,0 +1,39 @@ +const fizzBuzz = require('./index'); + +test('fizzBuzz function is defined', () => { + expect(fizzBuzz).toBeDefined(); +}); + +test('Calling fizzbuzz with `5` prints out 5 statements', () => { + fizzBuzz(5); + + expect(console.log.mock.calls.length).toEqual(5); +}); + +test('Calling fizzbuzz with 15 prints out the correct values', () => { + fizzBuzz(15); + + expect(console.log.mock.calls[0][0]).toEqual(1); + expect(console.log.mock.calls[1][0]).toEqual(2); + expect(console.log.mock.calls[2][0]).toEqual('fizz'); + expect(console.log.mock.calls[3][0]).toEqual(4); + expect(console.log.mock.calls[4][0]).toEqual('buzz'); + expect(console.log.mock.calls[5][0]).toEqual('fizz'); + expect(console.log.mock.calls[6][0]).toEqual(7); + expect(console.log.mock.calls[7][0]).toEqual(8); + expect(console.log.mock.calls[8][0]).toEqual('fizz'); + expect(console.log.mock.calls[9][0]).toEqual('buzz'); + expect(console.log.mock.calls[10][0]).toEqual(11); + expect(console.log.mock.calls[11][0]).toEqual('fizz'); + expect(console.log.mock.calls[12][0]).toEqual(13); + expect(console.log.mock.calls[13][0]).toEqual(14); + expect(console.log.mock.calls[14][0]).toEqual('fizzbuzz'); +}); + +beforeEach(() => { + jest.spyOn(console, 'log').mockImplementation(() => {}); +}); + +afterEach(() => { + console.log.mockRestore(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/index.js new file mode 100644 index 0000000..935ca22 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Given a linked list and integer n, return the element n +// spaces from the last node in the list. Do not call the +// 'size' method of the linked list. Assume that n will always +// be less than the length of the list. +// --- Examples +// const list = new List(); +// list.insertLast('a'); +// list.insertLast('b'); +// list.insertLast('c'); +// list.insertLast('d'); +// fromLast(list, 2).data // 'b' + +function fromLast(list, n) { + let slow = list.getFirst(); + let fast = list.getFirst(); + + while (n > 0) { + fast = fast.next; + n--; + } + + while (fast.next) { + slow = slow.next; + fast = fast.next; + } + + return slow; +} + +module.exports = fromLast; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/linkedlist.js new file mode 100644 index 0000000..2029b3b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/linkedlist.js @@ -0,0 +1,156 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor() { + this.head = null; + } + + insertFirst(data) { + this.head = new Node(data, this.head); + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getFirst() { + return this.head; + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + if (!node.next) { + return node; + } + node = node.next; + } + } + + clear() { + this.head = null; + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + // There are some existing nodes in our chain + last.next = new Node(data); + } else { + // The chain is empty! + this.head = new Node(data); + } + } + + getAt(index) { + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + + counter++; + node = node.next; + } + return null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + if (index === 0) { + this.head = this.head.next; + return; + } + + const previous = this.getAt(index - 1); + if (!previous || !previous.next) { + return; + } + previous.next = previous.next.next; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + const previous = this.getAt(index - 1) || this.getLast(); + const node = new Node(data, previous.next); + previous.next = node; + } + + forEach(fn) { + let node = this.head; + let counter = 0; + while (node) { + fn(node, counter); + node = node.next; + counter++; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/test.js new file mode 100644 index 0000000..e4684d5 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/fromlast/test.js @@ -0,0 +1,20 @@ +const fromLast = require('./index'); +const L = require('./linkedlist'); +const List = L.LinkedList; +const Node = L.Node; + +test('fromLast is a function', () => { + expect(typeof fromLast).toEqual('function'); +}); + +test('fromLast returns the node n elements from the end', () => { + const l = new List(); + + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertLast('e'); + + expect(fromLast(l, 3).data).toEqual('b'); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/index.js new file mode 100644 index 0000000..349c0c4 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/index.js @@ -0,0 +1,33 @@ +// --- Directions +// Given the root node of a tree, return +// an array where each element is the width +// of the tree at each level. +// --- Example +// Given: +// 0 +// / | \ +// 1 2 3 +// | | +// 4 5 +// Answer: [1, 3, 2] + +function levelWidth(root) { + const arr = [root, 's']; + const counters = [0]; + + while (arr.length > 1) { + const node = arr.shift(); + + if (node === 's') { + counters.push(0); + arr.push('s'); + } else { + arr.push(...node.children); + counters[counters.length - 1]++; + } + } + + return counters; +} + +module.exports = levelWidth; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/node.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/node.js new file mode 100644 index 0000000..5238e8f --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/node.js @@ -0,0 +1,10 @@ +module.exports = class Node { + constructor(data) { + this.data = data; + this.children = []; + } + + add(data) { + this.children.push(new Node(data)); + } +}; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/test.js new file mode 100644 index 0000000..35d20c2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/levelwidth/test.js @@ -0,0 +1,27 @@ +const Node = require('./node'); +const levelWidth = require('./index'); + +test('levelWidth is a function', () => { + expect(typeof levelWidth).toEqual('function'); +}); + +test('levelWidth returns number of nodes at widest point', () => { + const root = new Node(0); + root.add(1); + root.add(2); + root.add(3); + root.children[0].add(4); + root.children[2].add(5); + + expect(levelWidth(root)).toEqual([1, 3, 2]); +}); + +test('levelWidth returns number of nodes at widest point', () => { + const root = new Node(0); + root.add(1); + root.children[0].add(2); + root.children[0].add(3); + root.children[0].children[0].add(4); + + expect(levelWidth(root)).toEqual([1, 1, 2, 1]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/directions.html b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/directions.html new file mode 100644 index 0000000..3bae946 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/directions.html @@ -0,0 +1,378 @@ + + + + + +

Node Class API

+ + + + + + + + + + + + + + + + + + + +
FunctionArgumentsReturnsDirectionsExample
constructor(Data, Node)Node + Creates a class instance to represent a node. The node should + have two properties, 'data' and 'next'. Accept both + of these as arguments to the 'Node' constructor, then + assign them to the instance as properties 'data' and 'next'. + If 'next' is not provided to the constructor, then default its + value to be 'null'. + +
+            const n = new Node('Hi');
+            n.data // 'Hi'
+            n.next // null
+            const n2 = new Node('There', n);
+            n.next // returns n
+          
+
+ +

LinkedList Class API

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionArgumentsReturnsDirectionsExample
constructor-(LinkedList) + Create a class to represent a linked list. When created, + a linked list should have *no* head node associated with it. + The LinkedList instance will have one property, 'head', which + is a reference to the first node of the linked list. By default + 'head' should be 'null'. + +
+            const list = new LinkedList();
+            list.head // null
+          
+
insertFirst(data)- + Creates a new Node from argument 'data' and assigns the resulting + node to the 'head' property. Make sure to handle the case in which + the linked list already has a node assigned to the 'head' property. + +
+            const list = new LinkedList();
+            list.insertFirst('Hi There'); // List has one node
+          
+
size-(integer) + Returns the number of nodes in the linked list. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.size(); // returns 3
+          
+
getFirst-(Node) + Returns the first node of the linked list. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.getFirst(); // returns Node instance with data 'a'
+          
+
+ getLast + + - + + (Node) + + Returns the last node of the linked list + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.getLast(); // returns node with data 'a'
+          
+
+ clear + + - + + - + + Empties the linked list of any nodes. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.clear();
+            list.size(); // returns 0
+          
+
+ removeFirst + + - + + - + + Removes only the first node of the linked list. The list's head should + now be the second element. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.removeFirst();
+            list.getFirst(); // returns node with data 'a'
+          
+
+ removeLast + + - + + - + + Removes the last node of the chain + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.removeLast();
+            list.size(); // returns 1
+            list.getLast(); // returns node with data of 'b'
+          
+
+ insertLast + + (Data) + + - + + Inserts a new node with provided data at the end of the chain + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertLast('c');
+            list.getLast(); // returns node with data 'C'
+          
+
+ getAt + + (integer) + + (Node) + + Returns the node at the provided index + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.getAt(1); // returns node with data 'b'
+          
+
+ removeAt + + (integer) + + - + + Removes node at the provided index + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.removeAt(1);
+            list.getAt(1); // returns node with data 'a'
+          
+
+ insertAt + + (Data, integer) + + - + + Create an insert a new node at provided index. + If index is out of bounds, add the node to the end + of the list. + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.insertAt('Hi', 1)
+            list.getAt(1); // returns node with data 'Hi'
+          
+
+ forEach + + (function) + + - + + Calls the provided function with every node of the chain and the index + of the node. + +
+            const list = new List();
+
+            list.insertLast(1);
+            list.insertLast(2);
+            list.insertLast(3);
+            list.insertLast(4);
+
+            list.forEach((node, index) => {
+              node.data += 10;
+            });
+            list.getAt(0); // Returns node with data '11'
+          
+
+ for...of Loop + + - + + - + + Linked list should be compatible as the subject of a 'for...of' loop + +
+            const list = new List();
+
+            list.insertLast(1);
+            list.insertLast(2);
+            list.insertLast(3);
+            list.insertLast(4);
+
+            for (let node of list) {
+              node.data += 10;
+            }
+
+            node.getAt(1); // returns node with data 11
+          
+
+ diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/index.js new file mode 100644 index 0000000..5bd5efb --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/index.js @@ -0,0 +1,160 @@ +// --- Directions +// Implement classes Node and Linked Lists +// See 'directions' document + +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor() { + this.head = null; + } + + insertFirst(data) { + this.head = new Node(data, this.head); + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getFirst() { + return this.head; + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + if (!node.next) { + return node; + } + node = node.next; + } + } + + clear() { + this.head = null; + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + // There are some existing nodes in our chain + last.next = new Node(data); + } else { + // The chain is empty! + this.head = new Node(data); + } + } + + getAt(index) { + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + + counter++; + node = node.next; + } + return null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + if (index === 0) { + this.head = this.head.next; + return; + } + + const previous = this.getAt(index - 1); + if (!previous || !previous.next) { + return; + } + previous.next = previous.next.next; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + const previous = this.getAt(index - 1) || this.getLast(); + const node = new Node(data, previous.next); + previous.next = node; + } + + forEach(fn) { + let node = this.head; + let counter = 0; + while (node) { + fn(node, counter); + node = node.next; + counter++; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/test.js new file mode 100644 index 0000000..f4de046 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/linkedlist/test.js @@ -0,0 +1,321 @@ +const L = require('./index'); +const List = L.LinkedList; +const Node = L.Node; + +test('List is a class', () => { + expect(typeof List.prototype.constructor).toEqual('function'); +}); + +test('Node is a class', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); +}); + +describe('A Node', () => { + test('has properties "data" and "next"', () => { + const node = new Node('a', 'b'); + expect(node.data).toEqual('a'); + expect(node.next).toEqual('b'); + }); +}); + +describe('Insert First', () => { + test('appends a node to the start of the list', () => { + const l = new List(); + l.insertFirst(1); + expect(l.head.data).toEqual(1); + l.insertFirst(2); + expect(l.head.data).toEqual(2); + }); +}); + +describe('Size', () => { + test('returns the number of items in the linked list', () => { + const l = new List(); + expect(l.size()).toEqual(0); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + expect(l.size()).toEqual(4); + }); +}); + +describe('GetFirst', () => { + test('returns the first element', () => { + const l = new List(); + l.insertFirst(1); + expect(l.getFirst().data).toEqual(1); + l.insertFirst(2); + expect(l.getFirst().data).toEqual(2); + }); +}); + +describe('GetLast', () => { + test('returns the last element', () => { + const l = new List(); + l.insertFirst(2); + expect(l.getLast()).toEqual({ data: 2, next: null }); + l.insertFirst(1); + expect(l.getLast()).toEqual({ data: 2, next: null }); + }); +}); + +describe('Clear', () => { + test('empties out the list', () => { + const l = new List(); + expect(l.size()).toEqual(0); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + expect(l.size()).toEqual(4); + l.clear(); + expect(l.size()).toEqual(0); + }); +}); + +describe('RemoveFirst', () => { + test('removes the first node when the list has a size of one', () => { + const l = new List(); + l.insertFirst('a'); + l.removeFirst(); + expect(l.size()).toEqual(0); + expect(l.getFirst()).toEqual(null); + }); + + test('removes the first node when the list has a size of three', () => { + const l = new List(); + l.insertFirst('c'); + l.insertFirst('b'); + l.insertFirst('a'); + l.removeFirst(); + expect(l.size()).toEqual(2); + expect(l.getFirst().data).toEqual('b'); + l.removeFirst(); + expect(l.size()).toEqual(1); + expect(l.getFirst().data).toEqual('c'); + }); +}); + +describe('RemoveLast', () => { + test('RemoveLast removes the last node when list is empty', () => { + const l = new List(); + expect(() => { + l.removeLast(); + }).not.toThrow(); + }); + + test('RemoveLast removes the last node when list is length 1', () => { + const l = new List(); + l.insertFirst('a'); + l.removeLast(); + expect(l.head).toEqual(null); + }); + + test('RemoveLast removes the last node when list is length 2', () => { + const l = new List(); + l.insertFirst('b'); + l.insertFirst('a'); + + l.removeLast(); + + expect(l.size()).toEqual(1); + expect(l.head.data).toEqual('a'); + }); + + test('RemoveLast removes the last node when list is length 3', () => { + const l = new List(); + l.insertFirst('c'); + l.insertFirst('b'); + l.insertFirst('a'); + l.removeLast(); + + expect(l.size()).toEqual(2); + expect(l.getLast().data).toEqual('b'); + }); +}); + +describe('InsertLast', () => { + test('adds to the end of the list', () => { + const l = new List(); + l.insertFirst('a'); + + l.insertLast('b'); + + expect(l.size()).toEqual(2); + expect(l.getLast().data).toEqual('b'); + }); +}); + +describe('GetAt', () => { + test('returns the node at given index', () => { + const l = new List(); + expect(l.getAt(10)).toEqual(null); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + expect(l.getAt(0).data).toEqual(1); + expect(l.getAt(1).data).toEqual(2); + expect(l.getAt(2).data).toEqual(3); + expect(l.getAt(3).data).toEqual(4); + }); +}); + +describe('RemoveAt', () => { + test('removeAt doesnt crash on an empty list', () => { + const l = new List(); + expect(() => { + l.removeAt(0); + l.removeAt(1); + l.removeAt(2); + }).not.toThrow(); + }); + + test('removeAt doesnt crash on an index out of bounds', () => { + const l = new List(); + expect(() => { + const l = new List(); + l.insertFirst('a'); + l.removeAt(1); + }).not.toThrow(); + }); + + test('removeAt deletes the first node', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(0).data).toEqual(1); + l.removeAt(0); + expect(l.getAt(0).data).toEqual(2); + }); + + test('removeAt deletes the node at the given index', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(1).data).toEqual(2); + l.removeAt(1); + expect(l.getAt(1).data).toEqual(3); + }); + + test('removeAt works on the last node', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(3).data).toEqual(4); + l.removeAt(3); + expect(l.getAt(3)).toEqual(null); + }); +}); + +describe('InsertAt', () => { + test('inserts a new node with data at the 0 index when the list is empty', () => { + const l = new List(); + l.insertAt('hi', 0); + expect(l.getFirst().data).toEqual('hi'); + }); + + test('inserts a new node with data at the 0 index when the list has elements', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertAt('hi', 0); + expect(l.getAt(0).data).toEqual('hi'); + expect(l.getAt(1).data).toEqual('a'); + expect(l.getAt(2).data).toEqual('b'); + expect(l.getAt(3).data).toEqual('c'); + }); + + test('inserts a new node with data at a middle index', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertAt('hi', 2); + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + expect(l.getAt(3).data).toEqual('c'); + expect(l.getAt(4).data).toEqual('d'); + }); + + test('inserts a new node with data at a last index', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertAt('hi', 2); + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + }); + + test('insert a new node when index is out of bounds', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertAt('hi', 30); + + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + }); +}); + +describe('ForEach', () => { + test('applies a transform to each node', () => { + const l = new List(); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + l.forEach(node => { + node.data += 10; + }); + + expect(l.getAt(0).data).toEqual(11); + expect(l.getAt(1).data).toEqual(12); + expect(l.getAt(2).data).toEqual(13); + expect(l.getAt(3).data).toEqual(14); + }); +}); + +describe('for...of loops', () => { + test('works with the linked list', () => { + const l = new List(); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + for (let node of l) { + node.data += 10; + } + + expect(l.getAt(0).data).toEqual(11); + expect(l.getAt(1).data).toEqual(12); + expect(l.getAt(2).data).toEqual(13); + expect(l.getAt(3).data).toEqual(14); + }); + + test('for...of works on an empty list', () => { + const l = new List(); + expect(() => { + for (let node of l) { + } + }).not.toThrow(); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/index.js new file mode 100644 index 0000000..f1d0651 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/index.js @@ -0,0 +1,63 @@ +// --- Directions +// Write a function that accepts an integer N +// and returns a NxN spiral matrix. +// --- Examples +// matrix(2) +// [[undefined, undefined], +// [undefined, undefined]] +// matrix(3) +// [[1, 2, 3], +// [8, 9, 4], +// [7, 6, 5]] +// matrix(4) +// [[1, 2, 3, 4], +// [12, 13, 14, 5], +// [11, 16, 15, 6], +// [10, 9, 8, 7]] + +function matrix(n) { + const results = []; + + for (let i = 0; i < n; i++) { + results.push([]); + } + + let counter = 1; + let startColumn = 0; + let endColumn = n - 1; + let startRow = 0; + let endRow = n - 1; + while (startColumn <= endColumn && startRow <= endRow) { + // Top row + for (let i = startColumn; i <= endColumn; i++) { + results[startRow][i] = counter; + counter++; + } + startRow++; + + // Right column + for (let i = startRow; i <= endRow; i++) { + results[i][endColumn] = counter; + counter++; + } + endColumn--; + + // Bottom row + for (let i = endColumn; i >= startColumn; i--) { + results[endRow][i] = counter; + counter++; + } + endRow--; + + // start column + for (let i = endRow; i >= startRow; i--) { + results[i][startColumn] = counter; + counter++; + } + startColumn++; + } + + return results; +} + +module.exports = matrix; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/test.js new file mode 100644 index 0000000..4476dda --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/matrix/test.js @@ -0,0 +1,29 @@ +const matrix = require('./index'); + +test('matrix is a function', () => { + expect(typeof matrix).toEqual('function'); +}); + +test('matrix produces a 2x2 array', () => { + const m = matrix(2); + expect(m.length).toEqual(2); + expect(m[0]).toEqual([1, 2]); + expect(m[1]).toEqual([4, 3]); +}); + +test('matrix produces a 3x3 array', () => { + const m = matrix(3); + expect(m.length).toEqual(3); + expect(m[0]).toEqual([1, 2, 3]); + expect(m[1]).toEqual([8, 9, 4]); + expect(m[2]).toEqual([7, 6, 5]); +}); + +test('matrix produces a 4x4 array', () => { + const m = matrix(4); + expect(m.length).toEqual(4); + expect(m[0]).toEqual([1, 2, 3, 4]); + expect(m[1]).toEqual([12, 13, 14, 5]); + expect(m[2]).toEqual([11, 16, 15, 6]); + expect(m[3]).toEqual([10, 9, 8, 7]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/index.js new file mode 100644 index 0000000..4ddbeac --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Given a string, return the character that is most +// commonly used in the string. +// --- Examples +// maxChar("abcccccccd") === "c" +// maxChar("apple 1231111") === "1" + +function maxChar(str) { + const charMap = {}; + let max = 0; + let maxChar = ''; + + for (let char of str) { + if (charMap[char]) { + charMap[char]++; + } else { + charMap[char] = 1; + } + } + + for (let char in charMap) { + if (charMap[char] > max) { + max = charMap[char]; + maxChar = char; + } + } + + return maxChar; +} + +module.exports = maxChar; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/test.js new file mode 100644 index 0000000..14918ee --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/maxchar/test.js @@ -0,0 +1,14 @@ +const maxChar = require('./index'); + +test('maxChar function exists', () => { + expect(typeof maxChar).toEqual('function'); +}); + +test('Finds the most frequently used char', () => { + expect(maxChar('a')).toEqual('a'); + expect(maxChar('abcdefghijklmnaaaaa')).toEqual('a'); +}); + +test('Works with numbers in the string', () => { + expect(maxChar('ab1c1d1e1f1g1')).toEqual('1'); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/index.js new file mode 100644 index 0000000..10503dc --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/index.js @@ -0,0 +1,27 @@ +// --- Directions +// Return the 'middle' node of a linked list. +// If the list has an even number of elements, return +// the node at the end of the first half of the list. +// *Do not* use a counter variable, *do not* retrieve +// the size of the list, and only iterate +// through the list one time. +// --- Example +// const l = new LinkedList(); +// l.insertLast('a') +// l.insertLast('b') +// l.insertLast('c') +// midpoint(l); // returns { data: 'b' } + +function midpoint(list) { + let slow = list.getFirst(); + let fast = list.getFirst(); + + while (fast.next && fast.next.next) { + slow = slow.next; + fast = fast.next.next; + } + + return slow; +} + +module.exports = midpoint; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/linkedlist.js new file mode 100644 index 0000000..b7da56b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/linkedlist.js @@ -0,0 +1,178 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor(values = []) { + this.head = null; + + for (let value of values) { + this.insertLast(value); + } + } + + clear() { + this.head = null; + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getAt(index) { + if (!this.head) { + return null; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + node = node.next; + counter++; + } + return null; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + let counter = 1; + let previous = this.head; + let node = this.head.next; + while (node) { + if (counter === index) { + previous.next = new Node(data, node); + return; + } + previous = node; + node = node.next; + counter++; + } + + previous.next = new Node(data, node); + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index - 1) { + if (node.next) { + return (node.next = node.next.next); + } else { + return (node.next = null); + } + } + node = node.next; + counter++; + } + } + + getFirst() { + return this.head; + } + + insertFirst(data) { + this.head = new Node(data, this.getFirst()); + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node.next) { + node = node.next; + } + + return node; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + last.next = new Node(data); + return last.next; + } else { + this.head = new Node(data); + return this.head; + } + } + + forEach(fn) { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + fn(node); + node = node.next; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/test.js new file mode 100644 index 0000000..277597e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/midpoint/test.js @@ -0,0 +1,46 @@ +const midpoint = require('./index'); +const L = require('./linkedlist'); +const Node = L.Node; +const LinkedList = L.LinkedList; + +test('Midpoint is a function', () => { + expect(typeof midpoint).toEqual('function'); +}); + +describe('Midpoint returns the middle node of an odd numbered list', () => { + test('when the list has 3 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + expect(midpoint(l).data).toEqual('b'); + }); + + test('when the list has 5 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertLast('e'); + expect(midpoint(l).data).toEqual('c'); + }); +}); + +describe('Midpoint returns the middle node of an even numbered list', () => { + test('when the list has 2 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + expect(midpoint(l).data).toEqual('a'); + }); + + test('when the list has 4 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + expect(midpoint(l).data).toEqual('b'); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/package.json b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/package.json new file mode 100644 index 0000000..7ab32a4 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/package.json @@ -0,0 +1,11 @@ +{ + "name": "dev", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/index.js new file mode 100644 index 0000000..43bffe8 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/index.js @@ -0,0 +1,25 @@ +// --- Directions +// Given a string, return true if the string is a palindrome +// or false if it is not. Palindromes are strings that +// form the same word if it is reversed. *Do* include spaces +// and punctuation in determining if the string is a palindrome. +// --- Examples: +// palindrome("abba") === true +// palindrome("abcdefg") === false + +function palindrome(str) { + return str.split('').every((char, i) => { + return char === str[str.length - i - 1]; + }); +} + +module.exports = palindrome; + +// function palindrome(str) { +// const reversed = str +// .split('') +// .reverse() +// .join(''); +// +// return str === reversed; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/test.js new file mode 100644 index 0000000..abdbcb1 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/palindrome/test.js @@ -0,0 +1,33 @@ +const palindrome = require('./index'); + +test('palindrome function is defined', () => { + expect(typeof palindrome).toEqual('function'); +}); + +test('"aba" is a palindrome', () => { + expect(palindrome('aba')).toBeTruthy(); +}); + +test('" aba" is not a palindrome', () => { + expect(palindrome(' aba')).toBeFalsy(); +}); + +test('"aba " is not a palindrome', () => { + expect(palindrome('aba ')).toBeFalsy(); +}); + +test('"greetings" is not a palindrome', () => { + expect(palindrome('greetings')).toBeFalsy(); +}); + +test('"1000000001" a palindrome', () => { + expect(palindrome('1000000001')).toBeTruthy(); +}); + +test('"Fish hsif" is not a palindrome', () => { + expect(palindrome('Fish hsif')).toBeFalsy(); +}); + +test('"pennep" a palindrome', () => { + expect(palindrome('pennep')).toBeTruthy(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/index.js new file mode 100644 index 0000000..003b0a0 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/index.js @@ -0,0 +1,55 @@ +// --- Directions +// Write a function that accepts a positive number N. +// The function should console log a pyramid shape +// with N levels using the # character. Make sure the +// pyramid has spaces on both the left *and* right hand sides +// --- Examples +// pyramid(1) +// '#' +// pyramid(2) +// ' # ' +// '###' +// pyramid(3) +// ' # ' +// ' ### ' +// '#####' + +function pyramid(n, row = 0, level = '') { + if (row === n) { + return; + } + + if (level.length === 2 * n - 1) { + console.log(level); + return pyramid(n, row + 1); + } + + const midpoint = Math.floor((2 * n - 1) / 2); + let add; + if (midpoint - row <= level.length && midpoint + row >= level.length) { + add = '#'; + } else { + add = ' '; + } + pyramid(n, row, level + add); +} + +module.exports = pyramid; +// +// function pyramid(n) { +// const midpoint = Math.floor((2 * n - 1) / 2); +// +// for (let row = 0; row < n; row++) { +// let level = ''; +// +// for (let column = 0; column < 2 * n - 1; column++) { +// if (midpoint - row <= column && midpoint + row >= column) { +// level += '#'; +// } else { +// level += ' '; +// } +// } +// +// console.log(level); +// } +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/test.js new file mode 100644 index 0000000..8ffc318 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/pyramid/test.js @@ -0,0 +1,37 @@ +const pyramid = require('./index'); + +beforeEach(() => { + jest.spyOn(console, 'log'); +}); + +afterEach(() => { + console.log.mockRestore(); +}); + +test('pyramid is a function', () => { + expect(typeof pyramid).toEqual('function'); +}); + +test('prints a pryamid for n = 2', () => { + pyramid(2); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual('###'); + expect(console.log.mock.calls.length).toEqual(2); +}); + +test('prints a pryamid for n = 3', () => { + pyramid(3); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual(' ### '); + expect(console.log.mock.calls[2][0]).toEqual('#####'); + expect(console.log.mock.calls.length).toEqual(3); +}); + +test('prints a pryamid for n = 4', () => { + pyramid(4); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual(' ### '); + expect(console.log.mock.calls[2][0]).toEqual(' ##### '); + expect(console.log.mock.calls[3][0]).toEqual('#######'); + expect(console.log.mock.calls.length).toEqual(4); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/index.js new file mode 100644 index 0000000..829c30e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/index.js @@ -0,0 +1,56 @@ +// --- Directions +// Implement a Queue datastructure using two stacks. +// *Do not* create an array inside of the 'Queue' class. +// Queue should implement the methods 'add', 'remove', and 'peek'. +// For a reminder on what each method does, look back +// at the Queue exercise. +// --- Examples +// const q = new Queue(); +// q.add(1); +// q.add(2); +// q.peek(); // returns 1 +// q.remove(); // returns 1 +// q.remove(); // returns 2 + +const Stack = require('./stack'); + +class Queue { + constructor() { + this.first = new Stack(); + this.second = new Stack(); + } + + add(record) { + this.first.push(record); + } + + remove() { + while (this.first.peek()) { + this.second.push(this.first.pop()); + } + + const record = this.second.pop(); + + while (this.second.peek()) { + this.first.push(this.second.pop()); + } + + return record; + } + + peek() { + while (this.first.peek()) { + this.second.push(this.first.pop()); + } + + const record = this.second.peek(); + + while (this.second.peek()) { + this.first.push(this.second.pop()); + } + + return record; + } +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/stack.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/stack.js new file mode 100644 index 0000000..2032acb --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/stack.js @@ -0,0 +1,19 @@ +class Stack { + constructor() { + this.data = []; + } + + push(record) { + this.data.push(record); + } + + pop() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Stack; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/test.js new file mode 100644 index 0000000..3fc84c7 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/qfroms/test.js @@ -0,0 +1,41 @@ +const Queue = require('./index'); + +test('Queue is a class', () => { + expect(typeof Queue.prototype.constructor).toEqual('function'); +}); + +test('can add elements to a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + }).not.toThrow(); +}); + +test('can remove elements from a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + q.remove(); + }).not.toThrow(); +}); + +test('Order of elements is maintained', () => { + const q = new Queue(); + q.add(1); + q.add(2); + q.add(3); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); + expect(q.remove()).toEqual(3); + expect(q.remove()).toEqual(undefined); +}); + +test('peek returns, but does not remove, the first value', () => { + const q = new Queue(); + q.add(1); + q.add(2); + expect(q.peek()).toEqual(1); + expect(q.peek()).toEqual(1); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/index.js new file mode 100644 index 0000000..e475d6e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/index.js @@ -0,0 +1,25 @@ +// --- Description +// Create a queue data structure. The queue +// should be a class with methods 'add' and 'remove'. +// Adding to the queue should store an element until +// it is removed +// --- Examples +// const q = new Queue(); +// q.add(1); +// q.remove(); // returns 1; + +class Queue { + constructor() { + this.data = []; + } + + add(record) { + this.data.unshift(record); + } + + remove() { + return this.data.pop(); + } +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/test.js new file mode 100644 index 0000000..867bd42 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/queue/test.js @@ -0,0 +1,31 @@ +const Queue = require('./index'); + +test('Queue is a class', () => { + expect(typeof Queue.prototype.constructor).toEqual('function'); +}); + +test('can add elements to a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + }).not.toThrow(); +}); + +test('can remove elements from a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + q.remove(); + }).not.toThrow(); +}); + +test('Order of elements is maintained', () => { + const q = new Queue(); + q.add(1); + q.add(2); + q.add(3); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); + expect(q.remove()).toEqual(3); + expect(q.remove()).toEqual(undefined); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/index.js new file mode 100644 index 0000000..c2e6a0d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/index.js @@ -0,0 +1,21 @@ +// --- Directions +// Given an integer, return an integer that is the reverse +// ordering of numbers. +// --- Examples +// reverseInt(15) === 51 +// reverseInt(981) === 189 +// reverseInt(500) === 5 +// reverseInt(-15) === -51 +// reverseInt(-90) === -9 + +function reverseInt(n) { + const reversed = n + .toString() + .split('') + .reverse() + .join(''); + + return parseInt(reversed) * Math.sign(n); +} + +module.exports = reverseInt; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/test.js new file mode 100644 index 0000000..e5092e2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reverseint/test.js @@ -0,0 +1,23 @@ +const reverseInt = require('./index'); + +test('ReverseInt function exists', () => { + expect(reverseInt).toBeDefined(); +}); + +test('ReverseInt handles 0 as an input', () => { + expect(reverseInt(0)).toEqual(0); +}); + +test('ReverseInt flips a positive number', () => { + expect(reverseInt(5)).toEqual(5); + expect(reverseInt(15)).toEqual(51); + expect(reverseInt(90)).toEqual(9); + expect(reverseInt(2359)).toEqual(9532); +}); + +test('ReverseInt flips a negative number', () => { + expect(reverseInt(-5)).toEqual(-5); + expect(reverseInt(-15)).toEqual(-51); + expect(reverseInt(-90)).toEqual(-9); + expect(reverseInt(-2359)).toEqual(-9532); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/index.js new file mode 100644 index 0000000..5f036a9 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/index.js @@ -0,0 +1,30 @@ +// --- Directions +// Given a string, return a new string with the reversed +// order of characters +// --- Examples +// reverse('apple') === 'leppa' +// reverse('hello') === 'olleh' +// reverse('Greetings!') === '!sgniteerG' + +function reverse(str) { + return str.split('').reduce((rev, char) => char + rev, ''); +} + +module.exports = reverse; + +// function reverse(str) { +// return str +// .split('') +// .reverse() +// .join(''); +// } + +// function reverse(str) { +// let reversed = ''; +// +// for (let character of str) { +// reversed = character + reversed; +// } +// +// return reversed; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/test.js new file mode 100644 index 0000000..8d264c0 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/reversestring/test.js @@ -0,0 +1,13 @@ +const reverse = require('./index'); + +test('Reverse function exists', () => { + expect(reverse).toBeDefined(); +}); + +test('Reverse reverses a string', () => { + expect(reverse('abcd')).toEqual('dcba'); +}); + +test('Reverse reverses a string', () => { + expect(reverse(' abcd')).toEqual('dcba '); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/sorting/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/sorting/index.js new file mode 100644 index 0000000..5ad4201 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/sorting/index.js @@ -0,0 +1,66 @@ +// --- Directions +// Implement bubbleSort, selectionSort, and mergeSort + +function bubbleSort(arr) { + // Implement bubblesort + for (let i = 0; i < arr.length; i++) { + for (let j = 0; j < (arr.length - i - 1); j++) { + if (arr[j] > arr[j+1]) { + const lesser = arr[j+1]; + arr[j+1] = arr[j]; + arr[j] = lesser; + } + } + } + + // return the sorted array + return arr; +} + +function selectionSort(arr) { + for (let i = 0; i < arr.length; i++) { + let indexOfMin = i; + + for (let j = i+1; j { + test('sorts an array', () => { + expect(bubbleSort(getArray())).toEqual(getSortedArray()); + }); +}); + +describe('Selection sort', () => { + test('sorts an array', () => { + expect(selectionSort(getArray())).toEqual(getSortedArray()); + }); +}); + +describe('Merge sort', () => { + test('merge function can join together two sorted arrays', () => { + const left = [1, 10]; + const right = [2, 8, 12]; + + expect(merge(left, right)).toEqual([1,2,8,10,12]); + }); + + test('sorts an array', () => { + expect(mergeSort(getArray())).toEqual(getSortedArray()); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/index.js new file mode 100644 index 0000000..7e95441 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Create a stack data structure. The stack +// should be a class with methods 'push', 'pop', and +// 'peek'. Adding an element to the stack should +// store it until it is removed. +// --- Examples +// const s = new Stack(); +// s.push(1); +// s.push(2); +// s.pop(); // returns 2 +// s.pop(); // returns 1 + +class Stack { + constructor() { + this.data = []; + } + + push(record) { + this.data.push(record); + } + + pop() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Stack; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/test.js new file mode 100644 index 0000000..457e5a2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/stack/test.js @@ -0,0 +1,36 @@ +const Stack = require('./index'); + +test('Stack is a class', () => { + expect(typeof Stack.prototype.constructor).toEqual('function'); +}); + +test('stack can add and remove items', () => { + const s = new Stack(); + s.push(1); + expect(s.pop()).toEqual(1); + s.push(2); + expect(s.pop()).toEqual(2); +}); + +test('stack can follows first in, last out', () => { + const s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + expect(s.pop()).toEqual(3); + expect(s.pop()).toEqual(2); + expect(s.pop()).toEqual(1); +}); + +test('peek returns the first element but doesnt pop it', () => { + const s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + expect(s.peek()).toEqual(3); + expect(s.pop()).toEqual(3); + expect(s.peek()).toEqual(2); + expect(s.pop()).toEqual(2); + expect(s.peek()).toEqual(1); + expect(s.pop()).toEqual(1); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/index.js new file mode 100644 index 0000000..fd73326 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/index.js @@ -0,0 +1,50 @@ +// --- Directions +// Write a function that accepts a positive number N. +// The function should console log a step shape +// with N levels using the # character. Make sure the +// step has spaces on the right hand side! +// --- Examples +// steps(2) +// '# ' +// '##' +// steps(3) +// '# ' +// '## ' +// '###' +// steps(4) +// '# ' +// '## ' +// '### ' +// '####' + +function steps(n, row = 0, stair = '') { + if (n === row) { + return; + } + + if (n === stair.length) { + console.log(stair); + return steps(n, row + 1); + } + + const add = stair.length <= row ? '#' : ' '; + steps(n, row, stair + add); +} + +module.exports = steps; + +// function steps(n) { +// for (let row = 0; row < n; row++) { +// let stair = ''; +// +// for (let column = 0; column < n; column++) { +// if (column <= row) { +// stair += '#'; +// } else { +// stair += ' '; +// } +// } +// +// console.log(stair); +// } +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/test.js new file mode 100644 index 0000000..007af11 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/steps/test.js @@ -0,0 +1,34 @@ +const steps = require('./index'); + +beforeEach(() => { + jest.spyOn(console, 'log'); +}); + +afterEach(() => { + console.log.mockRestore(); +}); + +test('steps is a function', () => { + expect(typeof steps).toEqual('function'); +}); + +test('steps called with n = 1', () => { + steps(1); + expect(console.log.mock.calls[0][0]).toEqual('#'); + expect(console.log.mock.calls.length).toEqual(1); +}); + +test('steps called with n = 2', () => { + steps(2); + expect(console.log.mock.calls[0][0]).toEqual('# '); + expect(console.log.mock.calls[1][0]).toEqual('##'); + expect(console.log.mock.calls.length).toEqual(2); +}); + +test('steps called with n = 3', () => { + steps(3); + expect(console.log.mock.calls[0][0]).toEqual('# '); + expect(console.log.mock.calls[1][0]).toEqual('## '); + expect(console.log.mock.calls[2][0]).toEqual('###'); + expect(console.log.mock.calls.length).toEqual(3); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/index.js new file mode 100644 index 0000000..3bfb536 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/index.js @@ -0,0 +1,56 @@ +// --- Directions +// 1) Create a node class. The constructor +// should accept an argument that gets assigned +// to the data property and initialize an +// empty array for storing children. The node +// class should have methods 'add' and 'remove'. +// 2) Create a tree class. The tree constructor +// should initialize a 'root' property to null. +// 3) Implement 'traverseBF' and 'traverseDF' +// on the tree class. Each method should accept a +// function that gets called with each element in the tree + +class Node { + constructor(data) { + this.data = data; + this.children = []; + } + + add(data) { + this.children.push(new Node(data)); + } + + remove(data) { + this.children = this.children.filter(node => { + return node.data !== data; + }); + } +} + +class Tree { + constructor() { + this.root = null; + } + + traverseBF(fn) { + const arr = [this.root]; + while (arr.length) { + const node = arr.shift(); + + arr.push(...node.children); + fn(node); + } + } + + traverseDF(fn) { + const arr = [this.root]; + while (arr.length) { + const node = arr.shift(); + + arr.unshift(...node.children); + fn(node); + } + } +} + +module.exports = { Tree, Node }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/test.js new file mode 100644 index 0000000..69dab5d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/tree/test.js @@ -0,0 +1,67 @@ +const T = require('./index'); +const Node = T.Node; +const Tree = T.Tree; + +describe('Node', () => { + test('Node is a constructor', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); + }); + + test('Node has a data and children properties', () => { + const n = new Node('a'); + expect(n.data).toEqual('a'); + expect(n.children.length).toEqual(0); + }); + + test('Node can add children', () => { + const n = new Node('a'); + n.add('b'); + expect(n.children.length).toEqual(1); + expect(n.children[0].children).toEqual([]); + }); + + test('Node can remove children', () => { + const n = new Node('a'); + n.add('b'); + expect(n.children.length).toEqual(1); + n.remove('b'); + expect(n.children.length).toEqual(0); + }); +}); + +describe('Tree', () => { + test('starts empty', () => { + const t = new Tree(); + expect(t.root).toEqual(null); + }); + + test('Can traverse bf', () => { + const letters = []; + const t = new Tree(); + t.root = new Node('a'); + t.root.add('b'); + t.root.add('c'); + t.root.children[0].add('d'); + + t.traverseBF(node => { + letters.push(node.data); + }); + + expect(letters).toEqual(['a', 'b', 'c', 'd']); + }); + + test('Can traverse DF', () => { + const letters = []; + const t = new Tree(); + t.root = new Node('a'); + t.root.add('b'); + t.root.add('d'); + t.root.children[0].add('c'); + + t.traverseDF(node => { + letters.push(node.data); + }); + + expect(letters).toEqual(['a', 'b', 'c', 'd']); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/index.js new file mode 100644 index 0000000..9f4da37 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/index.js @@ -0,0 +1,28 @@ +// --- Directions +// Given a node, validate the binary search tree, +// ensuring that every node's left hand child is +// less than the parent node's value, and that +// every node's right hand child is greater than +// the parent + +function validate(node, min = null, max = null) { + if (max !== null && node.data > max) { + return false; + } + + if (min !== null && node.data < min) { + return false; + } + + if (node.left && !validate(node.left, min, node.data)) { + return false; + } + + if (node.right && !validate(node.right, node.data, max)) { + return false; + } + + return true; +} + +module.exports = validate; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/node.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/node.js new file mode 100644 index 0000000..d19e208 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/node.js @@ -0,0 +1,21 @@ +class Node { + constructor(data) { + this.data = data; + this.left = null; + this.right = null; + } + + insert(data) { + if (data < this.data && this.left) { + this.left.insert(data); + } else if (data < this.data) { + this.left = new Node(data); + } else if (data > this.data && this.right) { + this.right.insert(data); + } else if (data > this.data) { + this.right = new Node(data); + } + } +} + +module.exports = Node; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/test.js new file mode 100644 index 0000000..6ea4dc3 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/validate/test.js @@ -0,0 +1,23 @@ +const Node = require('./node'); +const validate = require('./index'); + +test('Validate recognizes a valid BST', () => { + const n = new Node(10); + n.insert(5); + n.insert(15); + n.insert(0); + n.insert(20); + + expect(validate(n)).toEqual(true); +}); + +test('Validate recognizes an invalid BST', () => { + const n = new Node(10); + n.insert(5); + n.insert(15); + n.insert(0); + n.insert(20); + n.left.left.right = new Node(999); + + expect(validate(n)).toEqual(false); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/index.js new file mode 100644 index 0000000..379ba6c --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/index.js @@ -0,0 +1,28 @@ +// --- Directions +// Write a function that returns the number of vowels +// used in a string. Vowels are the characters 'a', 'e' +// 'i', 'o', and 'u'. +// --- Examples +// vowels('Hi There!') --> 3 +// vowels('Why do you ask?') --> 4 +// vowels('Why?') --> 0 + +function vowels(str) { + const matches = str.match(/[aeiou]/gi); + return matches ? matches.length : 0; +} + +module.exports = vowels; + +// function vowels(str) { +// let count = 0; +// const checker = ['a', 'e', 'i', 'o', 'u']; +// +// for (let char of str.toLowerCase()) { +// if (checker.includes(char)) { +// count++; +// } +// } +// +// return count; +// } diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/test.js new file mode 100644 index 0000000..0bbf430 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/vowels/test.js @@ -0,0 +1,17 @@ +const vowels = require('./index'); + +test('Vowels is a function', () => { + expect(typeof vowels).toEqual('function'); +}); + +test('returns the number of vowels used', () => { + expect(vowels('aeiou')).toEqual(5); +}); + +test('returns the number of vowels used', () => { + expect(vowels('abcdefghijklmnopqrstuvwxyz')).toEqual(5); +}); + +test('returns the number of vowels used', () => { + expect(vowels('bcdfghjkl')).toEqual(0); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/index.js new file mode 100644 index 0000000..0818cb2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/index.js @@ -0,0 +1,43 @@ +// --- Directions +// 1) Complete the task in weave/queue.js +// 2) Implement the 'weave' function. Weave +// receives two queues as arguments and combines the +// contents of each into a new, third queue. +// The third queue should contain the *alterating* content +// of the two queues. The function should handle +// queues of different lengths without inserting +// 'undefined' into the new one. +// *Do not* access the array inside of any queue, only +// use the 'add', 'remove', and 'peek' functions. +// --- Example +// const queueOne = new Queue(); +// queueOne.add(1); +// queueOne.add(2); +// const queueTwo = new Queue(); +// queueTwo.add('Hi'); +// queueTwo.add('There'); +// const q = weave(queueOne, queueTwo); +// q.remove() // 1 +// q.remove() // 'Hi' +// q.remove() // 2 +// q.remove() // 'There' + +const Queue = require('./queue'); + +function weave(sourceOne, sourceTwo) { + const q = new Queue(); + + while (sourceOne.peek() || sourceTwo.peek()) { + if (sourceOne.peek()) { + q.add(sourceOne.remove()); + } + + if (sourceTwo.peek()) { + q.add(sourceTwo.remove()); + } + } + + return q; +} + +module.exports = weave; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/queue.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/queue.js new file mode 100644 index 0000000..20044c2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/queue.js @@ -0,0 +1,25 @@ +// --- Directions +// Implement a 'peek' method in this Queue class. +// Peek should return the last element (the next +// one to be returned) from the queue *without* +// removing it. + +class Queue { + constructor() { + this.data = []; + } + + add(record) { + this.data.unshift(record); + } + + remove() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/test.js new file mode 100644 index 0000000..f173360 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/completed_exercises/weave/test.js @@ -0,0 +1,45 @@ +const weave = require('./index'); +const Queue = require('./queue'); + +test('queues have a peek function', () => { + const q = new Queue(); + expect(typeof q.peek).toEqual('function'); +}); + +test('peek returns, but does not remove, the first value', () => { + const q = new Queue(); + q.add(1); + q.add(2); + expect(q.peek()).toEqual(1); + expect(q.peek()).toEqual(1); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); +}); + +test('weave is a function', () => { + expect(typeof weave).toEqual('function'); +}); + +test('weave can combine two queues', () => { + const one = new Queue(); + one.add(1); + one.add(2); + one.add(3); + one.add(4); + const two = new Queue(); + two.add('one'); + two.add('two'); + two.add('three'); + two.add('four'); + + const result = weave(one, two); + expect(result.remove()).toEqual(1); + expect(result.remove()).toEqual('one'); + expect(result.remove()).toEqual(2); + expect(result.remove()).toEqual('two'); + expect(result.remove()).toEqual(3); + expect(result.remove()).toEqual('three'); + expect(result.remove()).toEqual(4); + expect(result.remove()).toEqual('four'); + expect(result.remove()).toBeUndefined(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/01/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/01/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/01/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/01/diagrams.xml new file mode 100644 index 0000000..8b9e993 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/01/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/02/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/02/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/02/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/02/diagrams.xml new file mode 100644 index 0000000..19e74dd --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/02/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/03/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/03/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/03/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/03/diagrams.xml new file mode 100644 index 0000000..d837be7 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/03/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/04/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/04/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/04/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/04/diagrams.xml new file mode 100644 index 0000000..2224edd --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/04/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/05/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/05/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/05/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/05/diagrams.xml new file mode 100644 index 0000000..ce1f41b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/05/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/06/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/06/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/06/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/06/diagrams.xml new file mode 100644 index 0000000..d593c22 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/06/diagrams.xml @@ -0,0 +1 @@ +7VpNc5swEP01TG8dQGDjY+zm45DOdCadaXJUQAY1MqJCxHZ/fSUjjDDEwTSKMxPwwfC0EtK+3Qde2QKL1eaawSz5TiNELNeONhb4Zrmu4wIgviSyLREfTEsgZjhSRjVwh/8iBdoKLXCE8oYhp5RwnDXBkKYpCnkDg4zRddNsSUnzrhmMUQu4CyFpo79wxBOFOrZdN9wgHCfq1oGvGh5h+BQzWqTqfpYLlrujbF7BaixlnycwomsNApcWWDBKeXm22iwQkb6t3Fb2u3qhdT9vhlLep4Pi6RmSAlUz3s2Lbytf7FaDpL1tgfk6wRzdZTCUrWvBvsASviLiyhGn+/VIWwIfEZnvPbKghDLRlNIUSVPO6BOqQOEoO5CffUvleOGT+RITolkqlwqcplxFj+Ora33E3SFwSHCcCiwUbkGicd72k3LdM2IcbTRI+e0a0RXibCtMVKtbBYOK8T2nay1igMISLVgmCoMqSOP90DVR4kRx1c2b28Hb5E8hw2Z+g+vzkc03ZHNqiExvTMLBtE1fp21iiDbHGXkbyhvowZsx8XSOqefPBDE0CqgRRk0JqDO+xgzmzfPOqKDjk28wb34P3swpqH/s/ZOuv4wSaohSYxI6GVNxKG8T54wSOh15G8rbtAdv5iQ0OCKhD7SwwNUooUYoNSahszEVB/MWnE9CO4qgtzh9Eiy59i3Oed5iUSyKH1DV8L8iRXe0glq+ky7CISQXqmGFo0jepjM2mtFzQnho1LreEWp3dmqdHbXk039cAL9Bq+O1ad1X3nRevTfgFQQt4lAUo2p9lPGExjSF5LJGD1ysMYw2mN9r5w/S5KvME+Eetr1XPXYXdVvOIeMXckdCz1WBXWE5b9UlqixCAvMchyWoTOQNfyPOt4pAWHAqoHr6t5RmnWGoM9uUAXBCTLwYBjktWKgcWz0lxdJiVJkp+ZNOPxosDBHI8XNz76WL+V1X4Su41QwyitMyR9XIPySgFSY80JQW3zmIonLEOqb2U+sXZvbrsi964Cx/Ka21KIN5Vu5nLfFGRuHwlP+PJ0JTDnqEiJHKbtCUDreSEk06gNNWDnAkfnorx3RUjndTjmp/V1cO/0Moh+8YVo4eGwijcpz+0uGfUTkmo3K8m3K4HcoRfAjlmASGlcMdlcNEIc89o3J476Mcn0YdgBElaKV6cFi58O2v05l2+M0RS7VSgxyEx4ki0GPXcxSB00tRszOKQHtfLS2kxWcsQLlvQGYwO8jOjgKU11F/ck+vP4nL+n+bZTrXf44Fl/8A7ZtRc5s4EMc/jeeeroMQYPxYp8nlIde5uXTm2kcVZKNGRpws1/Z9+pOMMMIiLnbAPETOjAMrIcT+dv/AgifwbrX7g6Mi+5OlmE58L91N4KeJ78d+KL+VYV8aYBiXhiUnaWkCteGZ/Ie10dPWDUnxutFRMEYFKZrGhOU5TkTDhjhn22a3BaPNvRZoiS3Dc4Kobf2HpCLTVuB5dcMjJstM7zoOdcN3lLwsOdvken8THy4On7J5haqxdP91hlK2NUzwfgLvOGOiXFrt7jBVrq3cVm738Errcd4c56LLBn65wU9EN7ia8WFeYl/54nA0WPX3JnC+zYjAzwVKVOtWwpe2TKyoXANy8Xg8qi9F3zGdHz1yxyjjsilnOVZdBWcvuDJKR3mx+ju2VI6XPpkvCKVGT+1SaWe50NEDQr1ujnj4SDuiZJlLWyLdgmXjXB825gLvXnUdOAKRcY7ZCgu+l130Bn4VDDrGj0y3RsRAbcuMYIm0DekgXR6HrkHJBc2qnRts4Rb9u1FhM38k9bKj2SPN6UAwA5eEV2Ob/hpbNBC20GG7FhvsgG0w7YzOaOeXDHPs5HMQoEPJ59Tl4bXYgmA8+YwdtmuxhR2wDSafs3OXnmz7m9PPgYgOpZ/VTbfLxMu5RWA8AQXAcbuW27QDt8EUFLRVXSrJ/MY2E/jgJHQQpINJaFs9xnHrxi0eUULt0ssTyV8kJd97ImuxtijK4xQnqBr+11BMR2uT5TvlNZIg+lE3rEiaqt20xkYzei4IDwOtH5xBe+injxP0gDWAYQMraMF6LLqZXIM+uHaozUgfFmox2XC6n3PpPyx+nZg1h3HT9CxLK9Q4E0gQpmy/z7x+8tY/vWQNYgtw2MIXVIWzNwG2izifWYrfT7r2ArCZoTCwMzRoAej3kaAdijYuQd9ak5s1EzS2+bYlaOT3wNeu7nxCArn8vIRfHIyXn21VHpefveZnBJr6K6+Eb5afvl3z+RsvsJy6xKZetpBfn1Vuyn/uvHohV795YQTD2c3ytpqtgQqnS1xd2DMuMrZkOaL3tfXEqQZTvCPiq7H8TXX5oG4QpSv4/qve4rBSt60F4uKjegvHTF5peyBq3nqTtOqRULRek6Q06i5qhz+wEHuNDG1kRMJ5Pf0nxorWwDNZNnUBXhwFynPnY0A6mm14ontVGimPdYmrZG0PFY6p1JOfzeHbwB82la5Ce6NDwUhe3pvqkf9SBuPMEcCmsoTgJIjKEeuQOk6tW5S1FbBOw45SUqxfy2MjyNC6KF/hWpCdCsLrc/wNZ4jmbfA1Z4g+LsjjkxNCdQttCAcEtnDAM/HTWTigE47xhCOwhWM2hnCEYGDh6PCqkxOOy2tt4YjCETrhGE84Ils4yqdLt1aOKB5YOdre2nLK8fZ7lRGVY3ob5Xi/6hD3oQRWqsenD+xC78N0ZnxO6vulOOlBTsLjQhHo8M6YE4HLn8DORhQBu9CYb1SP91JwMp+7+j3AtLIzABbMoapP0K4qPmKUOph9PaIDs9s9AoB2kecLIi4zr5fZ8GYw5Wr9G8LyRFv/ThPe/w8=7Vpdb9sgFP01VteXyh+xmz42Wbs+bNOkTtr2SG1isxKIMGmS/fqBARsbp43y0WySkyqCwwVf33OAi10vms7XnxhYFF9oBrEX+tnaiz56YRgnN+JXAhsFhAbIGcoUFDTAI/oDNehrdIkyWLYMOaWYo0UbTCkhMOUtDDBGV22zGcXtqy5ADh3gMQXYRX+gjBcaDXy/aXiAKC/0pcexbngC6XPO6JLo63lhNKs+qnkOzFjavixARlcWFN150ZRRylVpvp5CLENrwqb63W9prf1mkPBdOoSqwwvAS2g8rvziGxOL6m6gtPe9aLIqEIePC5DK1pUgX2AFn2NRC0Sxvh9pi8ETxJM6IlOKKRNNhBIoTTmjz9CAIlD+WH7rFhN4EZPJDGFsWeqQCpwSrtUTxLpuj1h9BA4wyonAUhEWKBon+rYh43C9NXRBTYjQOaRzyNlGmOgOkRGD0Xik6ytLMQYrLLEkGgNapHk9dEOUKGiu+nmLHN4uvheQwYuBviPSd30q9gKHJpiJBUhXKeMFzSkB+K5BJ20iLdLgGvGfVvmXNLmKKyYA47dyPbR5E9g9kr5VA0GSGYsUg7JEqQK1iRz0N+R8o3kCS04F1Lj4mdKFUY8jCUNgWxJRh/rkFepVoGR0XudZBJMuWaqtRnrPACyHhrd+NTCIAUcv7dEP4XY0rKh7T8nrt6dkcqIpGQ+07UvbaHzGjTBxN8IHNOyCx+TuVLvg9TDl9qUtjs+3UgbulHOzGYzFUQ2+zRkoF+r8NkNryXMny3kfSmuqLErFPv7Om984blM6ih1KTd5oUxodIWcJrt8nHxWhYJufdeIpKv9brvqqLLbkqnZiGox31sXOmWnVVcQFbCyDBUWEl9bI3yTQyC0xR8j6CU1gK2YHe7+jMOXBlt7d9aq7EKlMXffqCLeOyW5aHg/L0yl2nOR8y1PPmSoDHDi0irvjnZSgFXVNhR1eDTkRk7FCKcC3umGOsgxvE8zeotj1EFzZ6fsMj0BmFHTIvBk5ZI560ofwCOlDz0mLSN4GMvdOHPzzkenmgsPMPOg8dhOdj0z3QDbMzMNOaePzkemmQSklpczJiPDaryCfwJX4/Uoz+EE+Nrn0wgRLbjP0Ioq5LJLgSk1pX15b/vnqCYuyFIhl3N9fqajpT5bS1R37116HvV6btx7T6sYurTHe9ix0PGOQLxkpdZD6xzn6bMBwxv+5uXCULKO9MQWB+5Cifgtj679+zXrQOxbfXc0q3Q2r2X50Ome4ODjVaiaqzStwdQZs/s0guvsL7ZpNc5swEIZ/Dcd2AIFjH2PHbg/NpT40PSqwBjUCuULEdn99JZDAGJw4DiXTGTh4pFeLkPZZfUSKhRbJ/gvH2/iehUAt1w73FrqzXHfq+vJXCYdSQP60FCJOwlJyamFN/oAWba3mJISsYSgYo4Jsm2LA0hQC0dAw52zXNNsw2vzqFkfQEtYBpm31BwlFrFXHtuuCr0CiWH966uuCRxw8RZzlqf6e5aJN8ZTFCTZ1afssxiHbHUloaaEFZ0yUqWS/AKpca9xWvrc6U1q1m0MqLnkBaVDPmOZgmlw0TByMM4rugHrBttB8FxMB6y0OVOlO0pdaLBIqc45MVh1SthQ/Ap1XLlkwyrgsSlkKylRw9gRGlJ6yi6cqMZ6XTplvCKVHlqviUTpLhQ4fZ6LzXTViSqJUaoH0C8jCue42cAH7s75zKiIy0IElIPhBmugXkIlWHeTOTOd3dci4ntbio2hBJoywDtOoqrtGJROa1hlykxY5xzYVj/R6oee4HfQmfcC76YLnj/CuhOf6Q8KbdsBzxpF3LbwqPwi8WRe8ceRdDe9mQHhmMW3Ac8eRdy08Dw0Jz2nB+w4B4+GI70J8Fa6P2LJ47oivX3yDblo8NOLrF9+g2xbPG/H1jG/QjUv7mGXE9y58w25d2mct95Cwon23Ycghy1ogZVfFCa0GAs3l2NdaarlPOY4EmN7qgoSEofpMZ3g0A+gNEXIp3T72of7JRmbShtl1cOb2wbJ99HKHBVa1ihHndWPz5gNxzlqoIIxgrbOMi5hFLMV0WasnTj1iCnsiHrSs0j9V+rOvcqls2IMxU5m6LBOYi1t17XA830ptRVS7y9rS0FgEFGcZCUpRm6haf4EQB40M54JJqW7+N8a2nYF3fipHb44C5bmXY0A6muU80FaePgmTfY1Am3lnYoUDxYI8N+t/F/n2MZzlTn7n6upkLn2ND3VWmoXlIJcuygORc5Dpp1RdFMkwjaHIi1j9bgjP1EwAFBLVefnF9nQwLtPdU8HEHKWZqWDasUz7HXPBtIe5wNT70mWWZLFVySDn9DDnkoMK3NcI1rj/J56cCTnkmNI+KRC9EPYnr/8ZhP7RPsxvn0EscRAXs0u5my7GqrpIsR8PAlSabarBPy7pl1OenVDu2m7b/azpMltfeBdlR/9UgJZ/AQ==7ZpRb5swEMc/DVI7aRU2gaaPTdpue6gmrZP27IADVgyOjNMk+/Q7G0NCTdU2o1TTiAqBv882vt+ZnKFeMM93XyRZZ/ciodzDfrLzghsP4ykOYa+FfSUE4bQSUsmSSkIH4YH9plb0rbphCS1bhkoIrti6LcaiKGisWhqRUmzbZkvB272uSUod4SEm3FV/sURlVkW+fyj4Slma2a6noS1YkHiVSrEpbH8eDpbmUxXnpG7L2pcZScT2SApuvWAuhVDVUb6bU65dW7utqnf3TGlz3ZIW6jUVcFXhkfANra/YXJfa174wo6Ha3veC2TZjij6sSaxLtwAftEzlHM4QHDbj0bacLCifNR6ZCy4kFBWioNpUSbGitQiO8s2nKakdDz6ZLRnnR5Z35qN1USgbPSiy510tEs7SArQY3EKhcGaHTaWiu2ddhxogEOdU5FTJPZjYCjgKqio2xtGVZbo9RAyeWC07CpagjiJiozRt2j6QggMLqxtc4IBDft3uCK8XeAh3wIt6YDfpYheO7E5kh8MB2YUd7NA4705lF6AB2UVd7MZ5dzK7ywHZXXaww+O8O5XdJBiQ3dRh94PGQiYjvVfSC6YfmK1cjfT6pTdovlL/vo74+sI3aMqC0IivZ3xDZi3Ifb4y4vsrfIMmLsh9ynJPc2Gu7zpJJC1LByQMVT2h1UJguRz72kqO+7TjWEz4tS3IWZLobjrDox1Ab4iQ19LtA6b/JI+JXJhdT8xwHyzdpy43RBHdqhpxnoRzgj8Qp7sgdNiB19b6MN5Ivp9J8BhVL99cD57/l261UiiimNDaZzTtCXCIXl531AvLY8CoF8LusvFnxvRPp085zfUQsH/GgNUODvC5rlrW05lU0/ni4mKc0W8Bfhm1gOOOXBf7k/eZ0thdqlTvNOBvphHD9gm2ELbFXlEN25j5nY9gR85v4NyxJH0/zu6a5ttS902riQt7yLH0iTS5MnCe6+rKXJ9pqlTVtyIrbacyvS9JblrIwbfaVuhGFTOiErBbws1CG8CWskdaND1UHZTaJhZFqYipb6tyIVabdWXy/Qyd/z+BZuzsOFEPURfVuXu9FOvI5bHfkTCgE96YwunhNbopO/pXheD2Dw==7Zpdb9owFIZ/DdJ2MyU24eOyULpdtNo0LrZduolJPIyNHFNgv352YueDuIXSwKQ1kUDO8bHjnOe1fRKlB6er3WeB1skDjzDtAS/a9eBtD4Dx2FP/2rDPDX1oDLEgUW7yS8Oc/MHGaN02JMJpzVFyTiVZ140hZwyHsmZDQvBt3W3Baf2qaxTjhmEeItq0/iCRTIzV97yy4gsmcWIuPQpMxSMKl7HgG2au1wNwkR159QrZvox/mqCIbysmOOvBqeBc5qXVboqpDq0NW97u7pnaYtwCM3lKA5A3eEJ0g+2Is3HJvY1FdjdY+3s9ONkmROL5GoW6dqvgK1siV1Sd+apY3I/2pegR00kRkSmnXKgqxhnWrlLwJbZGFSgvO4oaG3gVk8mCUFrxvMsObedMGvX4A3Pu6hFREjNlC1VYsKqcmNvGQuLds6HzCyBK55ivsBR75WIagAHMmxiN+1b021IxoG9sSUUs0KoIGZXGRd8lKVUwsNzgYAOc79l+O3itwPOBA96gBXZ9F7ugY3cmOxBckV3gYOd38+5cdtC/IruBi103785mN7wiu6GDHejm3bnsioT8GuxGDXbfcchF1NE7kR4cHc9WhsPLwPObmeYDXvFseDdRJHCaNjiqO5UHsGoEDJZqqI2pET0dN6IezG5MxYpEkb6MUx11/bxCIKfCbYOld8By0GTpemoAbbBsZp63SCLdq+xwnoWzD/4dTpvQVFDhKMZzc8qFTHjMGaKz0noQ1ApTvCPyZ6X8S7t8Ggb6lKmRFXX6JK8MMikgIW/0O5fqeqtsd0QPPLsKZpH1CClKUxLmRuOie/2NpdwbZmgjuTKV47/nfO1U3vNLOXy1DHToXhaBijTfiNB6mW1N3WuMa1SbYhGYIkme6v270GdNVazQvuKw5oTJtNLzN20oNRhYgdkHIhhUZXTcf+QdyC4fQSnC4lZOW2ZcG/6i2+1PXVIGdTyu3b4PL7Tbj7tcrd1czfV24lK5mt1UuonXysRzobvUxLOj7SZeWxPP9XriYhOv+Rap9UwMvJSJgXedimnDYSqWJyFXT8VG9SUEjo6kYgf+wAsOdPe2VMxGptsRWtkRXGvKxXaE8SXWFK+2pry0pAzf95LieroDb1xSTkbvfIDCasBqePpTCPV3T9hSgdaFVHYT+sQJPfDd6/NV3oPDZno+Q2GSKShP9TwURRnUFUYs1cPSvBP0VGDfIrrU5UTRiXVTxPJmRBI9mdQJ41HhviAs61b9YqVQVrnWNFO8+qOEYSR0gfPlZp3XfP3APjZU9d++CMz8zH36bcgMHn+EB55DZsUXRq/QmTotPxjKc4Tyoyw4+ws=7ZnPb5swFMf/lh2QtsuE7ZCmxyZttx26ScthZxe/AKrBkXFGsr9+BgyBmkgpQ/Qwc4jg+55/vc8zdoxHNunxi6T7+Ekw4B722dEj9x7GKxzo31I41QIJVrUQyYTVEjoL2+QPGNE36iFhkPcclRBcJfu+GIosg1D1NCqlKPpuO8H7re5pBJawDSm31V8JU7FRke+fDV8hiWLT9CowhmcavkRSHDLTnofJrrpqc0qbuox/HlMmio5EHjyykUKo+i49boCXoW3CVpd7vGBt+y0hU9cUwHWB35QfoOlx1S91amJRjQZKf98j6yJOFGz3NCythYavtVilXD8hfduOp/Tl9Bn4uo3IRnAhtSkTGZSuSooXaEQdKL+6WksTeB2T9S7hvOP5WF2lLjJlsgctzfNQjZQnUaa1UIcFtHFthg1SwfFi6FALROc5iBSUPGkXUwAvSV3E5Di6NUyLc8bghdHiTrKQJouoydKorftMSt8YWMPgiAUO+U29Dt4k8BAegLecgN1iiF3g2I1kh4MZ2QUD7JCbd2PZETQju+UQOzfvRrO7mZHdzQA77ObdWHYLMiO7lcXuJ4RCMkfvSnpk9Y67lVtHb1p6s+5XmvXV4ZsK36zLHkIO37T4Zl35kH2+4vD9G745lz5kn7I8QSqq/t0xJiHPLZB6qOoVrR4Cw6UbayNZ4SsDl4SU3xlDmjBWNjOYHv0EekOGXEt3Cpj+q33M0oY5dGKGp2Bpn7rcU0XLWpXDOQrnAr8jTntb+h0KLdTv1w/uBTt2ezPniQy+vL3xv2V5OWFEVvVFd0VPUinpKf+s7358zD79P3O18jPjRBMwD5p/IM3EXQwwJ9Mw14/nz1mVrfPJkDz8BQ==7Vpbb9sgFP41kbaXykCcy2PbtdukdZuWSdseqX3qsDomwqRJ9usHNvgGVbM0F2myHyL744DhfB+H46MMyPVi817Q5fyOx5AOcBBvBuTdAOPpNFC/GtiWwJAYIBEsLiFUAzP2BwxozVYshrxlKDlPJVu2wYhnGUSyhVEh+Lpt9sDT9luXNAEHmEU0ddEfLJZzg6IgqBs+AEvm5tWT0DTc0+gxEXyVmfcNMHkorrJ5Qe1Yxj6f05ivGxC5GZBrwbks7xaba0i1a63byn63z7RW8xaQyV064LLDE01XYGdczEturS+K1YC2Dwbkaj1nEmZLGunWtSJfYXO5SNUTUrfVerRtSu8hvao8cs1TLlRTxjPQplLwR7CgclRQXFWLdbzyydUDS9OG5W1xaZxn0qgHjcyzb0SasiRTWKTcAqrxyiwbhITNs65DFSFK58AXIMVWmZgOeETKLkbjyIp+XSsGDw02b4iFWBVRo9KkGrtmSt0YsvzEEYc4FNhxe/IOQh7CHvJGB+Bu6OMu7LnbkzscnpC70MMd6vfdvtwRdELuRj7u+n23N3fjE3I39nCH+323L3dVQn4K7iYOd98g4iLu2duRPTJ5OVsZj49D3tQh7w4WvJjdZRwLyHOHRrVQ2eGqRYBhpelpAznO025j6rvs0jQsWBzr13jF0ZbPP+hjV24PQWXQoXLkUun7aMAHoNKetQ0u31FJ9aiyp3MvOof4jHQihyqIE5iZRy7knCc8o+lNjXac2uAUNkz+bNz/0iYX41A/ZmpmVZt+KBvDQgpUyEtdcmmGW4XdMj3x4i2QxdYiSmmes6gEjYke9TdIuTWc0ZXkCqrn/4nzpVd5z0dy8s8y0K5riSDnKxFZyJRF1MISsMIY7iwWASmV7Kk9vo/6oqvyFd02DJacZTJvjPxVA7UGQysw+z1EwqaMXrafBB3ZlTOoRVgtZTddukWlb/DQH/a7hpRRmx7fYT8kxznskVtW6lO1V6VqvuLEsVI15BaW+o23/8bzUXe0jefWlfqN96qN56tOHGvj4XNnYvj/TsUcFXSys7EnO5ueJRUj7RAyRC+kYl37YdjR3StTMbds1p8I+58IvphyrBMB4z6mnDOmTD0xBZ8lpkw6MWL8Qkzp2OPgwDHFrQh+hrUC+oTlVQnLSUvy2C0FWvqCj1muy3Q8K+aipoKDTyx7hLi4yWV+oW6+vEFvB3oU5YpgBlRE2u47W4AjgP+2fljYmXWiAyhi1MkG0MSjiPAwilCP9b+MyihQ/5OL3PwF7Vpdb5swFP01eZ0w5iN5bNN2m9RJlfqw9dEFB7w6GBnna79+NtgEcNLSlDSbBJES+/ja4HvOvdhWJnC+3H7lKE9/sBjTievE2wm8mbhuOAPyWwG7CoD+tAISTuIKAnvgkfzBGnQ0uiIxLlqGgjEqSN4GI5ZlOBItDHHONm2zBaPtu+YowRbwGCFqoz9JLFKNAsfZN3zDJEn1rae+bnhG0UvC2SrT95u4cFFeVfMSmbG0fZGimG0aELydwDlnTFSl5XaOqXKtcVvV7+5Ia/3cHGeiTwe36rBGdKWnfk+yFxzfk0JIfE5RUcjf71khUBbhiRtQOe51TNaymKiigZ55F5F3bdmV8xU74+PSS1g9hyObNykR+DFHkWrdSFFJLBVLKmtAFms/KVuKnjG9rj09Z5Rx2ZSxDCtTwdkLNqAkwCmvusUQKn19vSCUNizvykvhLBNalSDQ9UMjIkqSTGKRdDfm9SzXmAu8PUoJqImW8YPZEgu+kya6AzTa0LEDZrq+aSgx1FjaECEw0YO0+pN67L0CZEGL4IiCZhZROJaxoauMi5QlLEP0do9et6ls0Ia3RPxS8Bdf155MSyYfrGpyQGiApy7wgDmRc1C+vakoRFxcqQhvEi6xO6KmVNrgLDYWkdIviSpQm6i7/8ZC7DTBaCWYhPYzu2csN7LrqSX4Ds1U/lVOfV0gkgO24pG2gjoLIp5gbRUclhHHFAmybo/+EUlAK0ekGMVjPJ8Yz27YM57hAOHsWdxdkLep+vThTb8y27z5n80b9Fq8QQ/YvMEDvAUD8OZbvAEThyN1g1B3KOKGYC4YI+5U2jznbdqCM9EWjrSdSpvfg7azJcqpxZvnByN1A1J3rkQ5GyPuZNrCyyVKs8kcdoNoytUG0G9tENubQ/+/2QXKxfe7d4HNLR8wJ1+NPd+0t1R6bwPLrtJVaNcwyBnJRNEY+UEBjVd1GLYVGLodEVUj7iVVP1o/lYG3s4PsQfICv50ZUJFXh4QLslUi7MjxcxJHzXxfhZxlhWWOd+pz2cBKHBDYiQMOcIwADjA4Jo6zJA74j2SJwHs1S/SwB8ezit27+1YMO/OpEqnu1RHuO9OTfSY2pqcB1jXTC6Yn+6gsRgJZtMrZic7Cs+V1TUXTvRqyPKZ8RSJEr3TDksQxPSaYk0XR9+yztNPzdAcgE3ptMj3Ht8j0DixS3SEWqfb5WaZ4G8k8eeHgXY5M+0htjMwPpVkQXo5M+6BtjMyPvTPdzyJTVvf/TKhWTft/f8Dbvw==7Vvfb6M4EP5r8roKmF953HbbvZO60kp9uOujAw7x1sGRcZrk/vqzwU4Akw1NSK1qTdUWPg9gzzfjYcYwAfer3XcG18sfNENk4k+z3QR8m/j+LInEXwnsayAA0xrIGc5qyDsCz/g/pEAttsEZKluCnFLC8boNprQoUMpbGGSMbttiC0rad13DHBnAcwqJif6DM75UqDedHhv+QjhfqlsnoWqYw/Q1Z3RTqPtNfLCotrp5BfW1lHy5hBndNiDwMAH3jFJe761294hI1Wq11ec9nmg99Juhgg85wa9PeINko4b+hItXlD3hkgv8nsCyFP//LkoOixRN/IiI695l+E3s5nJXQ3PWRcRdW3LVePle67jSEpL9mIrm7RJz9LyGqWzdCqMS2JKviDjyxO5BT1KWwDkidwdN31NCmWgqaIGkKGf0FWlQEDCttkOLJlTo+m6BCWlIPlabxGnBlVV6kTruuyIkOC8Elgp1I3YYZVP/ipI3xDjaNSDFx3dEV4izvRDRrWFYn6J8x4uUrWwblhgrbNkwQk97D1TWnx+ufbQAsaOMoN8ggG8QhTLhG+qQMr6kOS0geTiid20qG7ShHeb/SvhLqI5edEshOlY3zSJfAy8VMAVAAz8Rw2IMUrffagoh41+lhzcJF9gjlkOqZFCRaYlU2i9Oa1CJyLv/QpzvFcFww6mAjiN7onStzW6gLYF32MxJEynphqVK54Ga9CDLkZJSU6pk47dmxBCBHL+1Z7JrTCIw5oglgpnz5wv92Q8G+jMYwZ1DgzuLvCXyZwhvKmS2eQs/mrcYtHgDfg9voIe3aATeIoO3nCFU2CMv8ecgioaQl4UoyYJPQF6fz43BneeBW8RQvf9yiKd/SjCMzWA4sxUMYzehXuqTIgs865PRjXwycbRdShsIwrO03SwOzgze5nLPGndRmqD5YlAYhChZpJ+Au1uFwcAzaHJR8IooqLP7ZhgEga04qHvjZtT3e2XgnffKWwVCz6z4mW5KCF6X6DxnsFzX1dcF3kmeO+77MZQeqGpQ6gcfTKkfJm1KQWhQCjyTUjCGK5oFGkfpCF6qn2lsUGrWbTLIoUGrGArvTKMtrSsqmupVkKExqRicQvJVNaxwlpFTBnOxUQyNiJWcGqc/Aple0vHPJDDIDHqmXH+MKdcs5hSSN0fmxZMtsEemWQBwnnlVitKNnB9JplkWcJ55Vcz0LXqmWSv4gUQCl8kF7IUYuugFZa+4yKv+iO6I+4lfUi14VzulSb1b1Trhtn5nlTruqQr5N0piADj/xOuSz37iQt9iOQ+YqQqTvmeLu3kSBuEgp1skKUptl/OGcHezVS3gVrXeV8/rFOXOFvh0ftks8Hl18vABBT3gXhW43C9n9gp6YMCKpKv+vJvSyLNX/QFmWuJyzKv8E9jLMYGZlrgc8yrPnFrMMXsKsy5KDiQunlrMPLyeKixlsMgtvkyQxbP5sJR/sUCR9exjCH+3e6fOvXh1OXGxxfVmXWO9ddp4/KBg0vqY4POklL99xj1pBq1XRHQNdLz3QapThWLgviGwprjgZePKPyVwNLgk6DxvhV7TZgbITzs2VvfgxNlx+CVqbHH3Wq3WCLQHW2fb6pIduz4obKCpm496pu27VOzd09fM4kK8nipdLjYZ5/E99iyu9x2665KxkdhMLCZjoIfNjRT5U9gcgcAk6jwbAvPZcCQCxeHxw+Y6vh4/HgcP/wM=7ZrLcpswFIafhpl00Qwg48syceN0ka68aLtU4ATUyMgj5FufvgIOGCqcuja2N2ImE+nXQRLnl77RaOyQ6WL7LOky+SYi4I7vRluHfHF83/MJ0f9yZVcqARmVQixZhEF7Yc5+A4ouqisWQdYKVEJwxZZtMRRpCqFqaVRKsWmHvQneHnVJYzCEeUi5qX5nkUpQ9Vx33/AVWJzg0OMAG15p+B5LsUpxPMcnb8VTNi9o1RfGZwmNxKYhkSeHTKUQqiwttlPgeW6rtJXvzQ601vOWkKpjXhjgNNSu+nSIdCawKqRKRCxSyp/26mPxeZB34OpaohZcFz1dhC1TPxrln3nIfaBrmaJSPeTGaCkVKVTajHGOHUEaVREhp1nGwlLEkLzTX6DUDlcLXSmhpf0UX4RYYlympHiHqeBCFh9F3OKpWypPiVbeRKqwS2+I9a43zcxisjOxkiEmz8e1SmUMGIU7IU9r4zV04xnEApTc6QAJnCq2bi9Aius4ruP2XuoC2tltLc5lTfkKO2VpBnnKZabuIqroJ8P8trWbhCmYL2nxdRu909t212s3j+X0FfhjvfqrDNZeH2eInxug/W5EzornP4yinMVpvoi0USA/cm6tswHbD13BVlKBCXk2weqmAYchakmDC5V2jo/kgI8PpYmOr3twXevlsV4Gg396WeO5by8Di9s+cTs0cTu6FW6HB7bpC7W0PZO2NVqvgdvRMbhVCcvuM52eO+2q+9mz3p5K3y5vL4bfscVvn/idmPitdu71+Tsx9q2EhVhDedy1G/RU+OrhrgffamzDRU1fe8Q9GbJdHl4Msp5n+GQpewZlvY5LBe9mtwrVbIwdWpxz7RY9FbPEvSZmzTuFGrN/HW31nz3dngzeLlcvB157mdsveIMO8A5vBt7A2LN6VvZ0eyZ2R9fErnlHpC20R9uzCNth4OUIO7KE7ZWw4w7CTm5G2HHX9rTn2rMAOxhcE7DmJVAJWHuo7RG5XZb2hVxd3f/4oWhr/MKEPP0B \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/07/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/07/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/07/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/07/diagrams.xml new file mode 100644 index 0000000..15b0902 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/07/diagrams.xml @@ -0,0 +1 @@ +7ZxLc6s2FIB/jbcZ0IPH8iZN2kU705ks2i5lkDG9GHmwfOP011cYCQNyaoIRmkxFZjJwJDCcT0fnYeEVfNqdfq7IfvsbS2mxAl56WsGfVgDEsSf+14L3RoCgFGRVnjYi/yJ4zf+hUqi6HfOUHnodOWMFz/d9YcLKkia8JyNVxd763Tas6H/qnmRUE7wmpNClf+Qp30qp73mXhl9onm3lR0dYNqxJ8j2r2LGUn7cCcHPemuYdUdeS/Q9bkrK3jgg+r+BTxRhv9nanJ1rUqlVqa857+aC1ve+KlnzMCbg54QcpjlTd8fm++LvSxflpaN3fW8HHt23O6eueJHXrm4AvZFu+K8SRL3bb56n7FmRNi8dWI0+sYJVoKllJ6668Yt+pEgpFeVH917YoxQudPG7youj0lCoVclZyOXp8LI+7VzxvQk6KPCuFLBFqoaLxUT42rTg9fag6vwUixjllO8qrd9FFnYCk8uQYB1he4q0zYtS433YGSyBlRA7SrL30BZTYkayucws0bllFaWkPXgTWMAjGwEsxjVL0BeCFhtiFGiWaitlHHrKKb1nGSlI8X6SPfY4dZvSU8z87+3/VXR7wGQSp+Ld6MuxiE7KXvL6184VomaoeSUEOhzxphLJLfdG/KefvEhM5ciZEl1v8lbG9GjyaOSt+/REBB+SD/yDfKKrWTg/zgR2rRIoi6R1IlVFF3hs9GipaEJ7/6F/+HraRm0+nmiTwb5tkYMgkY4dtKjboQXtuUJl6B9y63rMGL0giut6McoOERpvkC8Az5QZ9X8Pk/OBkP+gD3RECi45Q3Y+bUidYZXjbKk15Qh/e5ibOEIk4vc2MHPZNdr7JTzXngfkug7RF1UEK0MJIgfKACmkQaEihryOFc5gickhNWGkU2UOq121SwomGVTwdH0yjPa1LFF31SpGmsVpXeUKKb7Jhl6dp8dGAmTwoxnrEcz/5nGAGmH7Qt0+oNNyBia5MuWCOKVcv5pQ1Nwdz6mQLsD2YobPMWWFCZR42YOrlHGeZ9/lM3x5MV+SZzA0Fg1hnySIP0Is8lWBkjd06wgjrCf01dlFCE9s1njHsTNV4gKvxzFjjURNWr8YTjh4Ps9d41P24GfXzVonhbas0VeMBrsZjBCkelO0WLAgAvcbj0o67vKbFSPXKqhyXdtxlmcheDnllqY5zkiO5BcDid8tAr+SwipSZxW+X0zBeXwkzr+KjgfXMYww+U5mHsniXeUzNPDTOg2TkysortFjm4dZZTbfK2N63y1Av5ehm6jKPzyINPXtfRapruMxjNU+wGkB7wSrUKzou87jPMu2lkQEyEQI1YU8bBP2fQyCI7gx35Km/s1x8SjtmosFaIYgHg6EJueRZg/HQ3sY4e9fLRhty0O19uVjqOssrjvflvH2CsZFYKuzP1QiFmnlHoW7eaA7zhs68zZo3NmLe2FvOvPVC4qEQlJx5jywCx31US5o3GpEquRT3g6grjHvcFq0bIj0h2h+rfWGxbhgHISSjXs6kfopp+AXwmaob4siEV3V1w9arImDEq8bQe0DeZeunXSDyH0Cn1cOmXC7SM2g3bY+0+wjdtntTlUnk1kQYQaqKEBYqk8itiZi5mBWDHswli1nIrYmYF2aEQ2swscttJnOLh28SLpnbYD23ySr6bg9ecN5GwcP13xeAZyyzcSsizGY22Exm43sRfhhEUYulM9ilM9PfKfW829ZuKp/BLp8xw3T4K0ULJjTYJTTzxsAx6i+FWjQGdgnNzK/we4NVUAZpisPLb3Q2bvXyO6jw+V8=7ZxNk5s4EIZ/ja8pQHwe48nM7mFzmkM2RxlkzEZGLlmO7fz6FUbCQDMxY/NRsyunKgUtgaEfdYt+kWeBnranPzjebb6yhNCFYyWnBfqycJwosuT/heFcGlykDCnPktJkXw2v2S+ijLrbIUvIvtFRMEZFtmsaY5bnJBYNG+acHZvd1ow2v3WHUwIMrzGm0PotS8RGWW3Lujb8SbJ0o7469FTDCsc/Us4Oufq+hYPWl0/ZvMX6XKr/foMTdqyZ0PMCPXHGRLm1PT0RWrhWu6087uWN1uq6OclFnwOc8oCfmB6IvuLLdYmz9sXlbkjR31qg5XGTCfK6w3HRepTwpW0jtlTu2XKzup+iL8UrQpeVR54YZVw25SwnRVfB2Q+ijdJRVlj8q1q046VPluuM0lpP5VJpZ7lQo8f21H79jJePtGOapbm0xdItRDYu1W0TLsjpTdfZFRA5zgnbEsHPsos6QI7q8pBza/9YGzF63G9qg8VXNqwGaVqd+gpKbihW3dwQ4JZyQvL54IXOCvl+H3iJR8LE/QDwgpHYuYASSWT2UbuMiw1LWY7p89W6bHKsMSOnTPxd2/5edPnkXUBgLj4XybCOTdpesuLSLicieaJ7xBTv91lcGlWX4qT/ECHOChM+CCZN10v8i7GdHjwgnDW/5ohALfL+b8iXjiq808C8ZwceK5OnZgfMU6IYBb0HAycUi+xn8+yPoPVMOr07IqPbEemPFJG+wXYvNpn455sFA8BtVWzNxs6PQ7Ja95oEMQnX8QdgN9YkGJpJcLhJMIKToD3jLBiZdHpvSLre7ZAcaxbUxffvuMkjZA1ObjPD+11ZmK+zU8G5FbzTIK1Q1ZA67sRIkRU1kaIIIEU2RIoGiETbNkjHiFI/mA8plGwSLDDAKu9OtNJow+sKRd29ygQ8VvgqizH9rBq2WZLQtwbM3YOi73x46afu0xkAZgVPwwxDANPtSLnOECkX6jh5wc3AvDvZuvPBdE1kDgsz8uaDCaUcE5mPzZnWfDCNwHM3N89tPetMKfDYUOHhktFs7Fah53qwnO9iF8Yknlvg6cNuLIHHNgrPgAqP3SHxaJhzSDy20Xjujkrfvh2VY2k8jtF4RkGKWrLdhIKAAzUeU3Y8NGvO+KSqw9GUHQPB9J1WsrVgsh0NJlR3zCTZk1tgtTLqlGWHA5UcxnGezvhqOQmiVcdjZic+4s9eefTBN9r6qokqD+kKfq6aip2yzflvlyVgEDQrFb2Ypl6poKB7sAxelpiVPA+EbHA7ZEcrS6DOA2PYlCXvRhrO955Sr/AxZclimCfZwJ7vbUjHkh5TljwWmfPVmAgKBmu8hzCnmyi7n1U6surL5fMObuOs/miyc0MbsNOJt87OHYIdLCn3VPrdsOv5SrmlvU7KDlaV5uG0t8Da5Ib0Cqwp5ADfgw+jjxeUqojUJWW9oKzVl9+refR/Wk+ijl/4lG+fJqgnEVwFsjvwHZ1RCIr8AOFeP7QjduKR4AME7lhCEOpRVZqE+5aAd5vbWGoAgqUjTMBGDXg3Uu1GjVT//GcCNQDBAtKoAQ/lVa9VhCD4IDtWAenCRQRGDRhS2hkRpty9/nWJS1vtL3ig538B7Zxdc6M2FIZ/jW8zCImvy3U2aS/amc7kou2lDDKmi5FHltd2f32FkTAgsiY2oKYVmcnAQXxYj450zotgAZ+3p58Y3m1+pQnJF66TnBbw68J1o8gR/0vDuTIgKA0py5LKBK6Gt+xvIo2q2CFLyL5VkFOa82zXNsa0KEjMWzbMGD22i61p3r7qDqdEM7zFONetv2cJ30grcJzrjp9Jlm7kpUNP7ljh+FvK6KGQ11u4cH1Zqt1brM4ly+83OKHHhgm+LOAzo5RXa9vTM8nLqlXVVh33+s7e+r4ZKfiQA9zqgO84PxB1x5f74mdVF5dfQ8ryzgIuj5uMk7cdjsu9RwFf2DZ8m4stIFbr31OWzfGK5Mu6Rp5pTpnYVdCClEU5o9+IMoqKcsLyr96jKl7UyXKd5XmjpKxSYacFl60HeHK7ecbLIuw4z9JC2GJRLUTsXMqfTRgnp3erDtRARDsndEs4O4siqpFLhLKJ10iPjQajmv2m0VZ8acOyjab1ma+cxIpE1Y8NathSRkhhjl3orqDvD2GXeCRM0L+fXTAROqRBIonoe+QmZXxDU1rg/OVqXbYxNpCRU8b/aKz/WRZ58i4cMONfyq6wSU3YXrPy1i4nIkWiSsQ53u+zuDLKIuVJ/yKcnyUlfOBUmK63+AulO9V2NGdW+NoNAnbA+z8AX1VUWTstynt6YLE0eXJswCwlklEwuC0wkmOefW+f/RG0nu1M73VI4N/2SH8ij/QttnuxuSg0NwgGGrdVuWaMnR+HZLUeNAZiEq7jT8BuqkEwtIPgeINgpA+CwOAoGNnu9F6XhOC2S041CqrU+0fcxBEiAye3meH9rkrL19mp5Nxx3nmQ1qgaSF00M1IQeG2k0NOQQqAjhSN4IgAW6RReCqE5pLpgk2CONazi1/FON9qqdYmiWb3SpNVYWVdZjPMvcsc2S5L8vQZzd6MYOh5eysnf6Y4AEzgd/wyRBhP1dLnuGF2uLuMUJTcL8+7O1jEHE1nPHBWm6wNzMHUpx3rmQ2OmUllMwLQCz93cEOjEOnMKPEBXeJhgZIzdKvSQp6fzfezCmMSmBZ4h7KYSeIBVeEZUeECPxKMeJJmQeIDVeO73yvC2V06l8bhW45kEadSR7WYUBFxd47Fpx0MwDUaqyh1t2jEWzMhcDtkzSccOkgO5eb7B58quruRQhovU4KPlJIhWPWFmLz7iG888huCbKvNQs3Bs5jFG5qEGw2bmoaIbE5mHnaxzv1f60NzT5Z7JOrqb2szjw0g9c48i1SQem3ksxglWvdBgsKorOjbzeMgzkbk00uvpWx8Pgaqwpw6C/tMhkMa5HRXBR8MdeehvNBNXub6VoOZgndVlOo2hisLkUZ32UN/GsBdIdNlojfe6v88XS/Wz7Bl4Xy/LBxhPkuEE7VgKqYeMDfcOA9290RjuDTRM1r1HdW84iXujIJrNvXXtaZ8LSta9B+qGsD0rbE73hrr8ZJDb50pxA6XdGXkpU580tDuwXW5QN4z8AOJBr2USkHgk+AT4ptINoT/FqPp/1Q3hBC+g9I+qYeA9dXQtz3lyncbiTTbMDlC1bFf9jq9Ht319KjUS6tKV7vxWjfwo0tBpB7hzqpFQF7CsGvmQf6rOzYCApc5r1ciRYIaOaw7mgLfQ7CD5Drfu24Nz5jPI1cCljJzNwfMvyyB4Xvn3CeBN9pUZqAc0Npu5N5tBE8y17s9mgAOdJxBdF1OpDbIq1P1fl0K3HX+q1AYN+AiRTW0+jrT7faIZUxukz3myqc1DA3PY6VXnjIZ1ycimNg95ZncK1JwwdR2pEJuXNUePwOzTtmGz9OuMppnlqHGs1buiDzMUm9evq1Zx0fULtvDlHw== \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/08/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/08/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/08/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/08/diagrams.xml new file mode 100644 index 0000000..c461e6e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/08/diagrams.xml @@ -0,0 +1 @@ +7ZlNc5swEIZ/Dcd2AIHtHhvXTg/tKYe2RwXWoEZmPUL+6q+vgAXMyMk4nthcpIvRq9XXPpJfxvbYfH14VHyT/8QUpBf66cFj37wwDEwxH5VybJSYTRshUyKloF54Ev+ARJ/UrUihHARqRKnFZigmWBSQ6IHGlcL9MGyFcjjrhmdgCU8Jl7b6S6Q6b/fl+33DdxBZTlPPYmp45slLpnBb0HxeyFZ1aZrXvB2L4sucp7g/kdjCY3OFqJun9WEOssptm7am3/KV1m7dCgp9SYcvtAx9bLcOqckEVVHpHDMsuFz06kO9PagG8E0t12tpHgPzCAehf1fy55hqf6il1FzprxUYIxRYQKsthZQ0EBRpG5FIXpYiaUQKqYb5C1of6bTwrUYj9Uv8gbjpplP4AnOUqOpNMb8uXUvLlBllhYWmIYMJ1c/1tDNLyS5xqxJKXkhnlasMKCpqpCqtJ92IxiPgGrQ6mgAFkmuxGx5ATuc46+J6luaBcL5yFvzbsA0d3A4uGw1ucBu4Uwe3gxuPBZfWsuNy267OvstDmPtcaHja8Ho7e2PKQ8CdzVSxkj+DfOiMqk1ZB/cyAmGVcQP4JHJZl3eQ4VJkRXVqDBlQb6HagdJweBMDtUYzyhW9egSM6vveyFu3zk8sPPI/4FaGzk4/8lIy+1JOR/vGZc5Obw13MhrcyNnpreHOxoLLLDt1bnqxmwZDNw3v6KaRxS1y4K59DbonuNgC9ymIHbkLycXxeOQmFrkzr7QO3HlwLBqCY3cEN7WvnAN3rcndE9zMvnGO25Ued0Nuptr/KF+3nfzzwRb/AQ==7ZpPl5owEMA/Dcf2AQHU46672x7avr63h26PWYiQbiS+EFftp28CA4jBLbpKDw0HTSaTP+Q3k0miDpovt58EXmVfeUKY47vJ1kF3ju9H3kx9asGuEvgRCFJBk0rktYJH+puA0AXpmiak6ChKzpmkq64w5nlOYtmRYSH4pqu24Kzb6wqnxBA8xpiZ0h80kRlIPddtCz4TmmbQ9TSEgmccv6SCr3Poz/HRonyq4iWu2wL9IsMJ3+yJ0L2D5oJzWaWW2zlhemrraavqPRwpbcYtSC6HVPBhGHJXvzpJ1ExAlguZ8ZTnmN230tvy9YhuwFW5TC6ZSnoqSbZUPmnxxxByP6GkkFjIGw1GCXKek1r2QBmDhkie1Boxw0VB40oIKrqZX0TKHVgLXkuuRO0Qv3C+aroT/IXMOeOifCnklk9TUjNFSrLguYQmvQjyfTWridKzc3SqQVTwtYhBKwTjxSIltVbLWbkP4UsixU7pCMKwpK/d5jEYctrotTBVAnj2s0XXYetbuMfhzkZiG1yH7cSyfcNxvZHgQt+vmK2h0SZctLy7NDcZleRxhcvhb1RM7hJuwozWZfiZsNsmUNVz1tAdhsDXU64I72k+lM8JaDCjaa7NRpEgomH1SoQk27dpmRigQjCFuYKth4cgv2kDeR2ts70QHrjvBxfZaHpVp5z1OCUaySknNpqOD9cfCe7UhtPx4QYjwZ0Z4dRG08HR1OtGU3/EaFp3vQcusOTO3QeNSs4zyH3wQotuILow/IfofANdLbLk/koOBV1yaExyyHQ6S+7cQDcqucD0OQvuzDg3KrjrHPj3Dg1w+M/VwJ5qNZ1py/7bI4XXc0UX9pvKxY8UnnlF940nxLAGZdbywDM78we89v0KRIaraCehMWY3ULCkSVLaU99S0LWxE1aD05C9y3Gjg1jpBabjBj2O61/CcScGP7vgDuQ28Q+4zUKD26yH2+QS3KYGtwRLbNldmR0KL8DOvIeJM8oSNXYnvHXCO0vxTIp958NrUay77qycEdNRjqpEqhM3qjwvw2FVoNpsymyIPAU0Ql3QExN0FF4nRPYcQeyPWSftX/c3pvX+YgD7wZtVqPqdU9Vie3k0Cfttpm6i2kNDrQN7aIYxzETMuyJ743D2Ld+YB1ffvCvSa4ZLC223mVq5XWNVhzfrXdMjvNQg8+dCf/GFqm/e1NuV/o2Lw8ONWc9KP/UvstKrbPv/wsrr2/9wovs/7ZpNc5swEIZ/Dcd2QAIcHxM3aQ/tTGdyaHuUQQY1AnmEHNv99ZVgAcvg1LETehEHI71afaBnxUq2Pbwodp8lWeffREq5h/x05+FPHkJxMNefRtg3AopByCRLGynohUf2h4Log7phKa0sQyUEV2xti4koS5ooSyNSiq1tthLc7nVNMjoQHhPCh+oPlqoc1MD3+4IvlGU5dH0TQcGSJE+ZFJsS+vMQXtVXU1yQti2wr3KSiu2BhO89vJBCqCZV7BaUm6ltp62p93CitBu3pKU6pwKCYah9++g01TMBWSFVLjJREn7fq3f141HTgK9zuSq4TgY6SXdM/TTyxwhyv6CkUkSqWwNGC6Uoaas9MM6hIVqmrUXCSVWxpBHBxDTzmyq1B28hGyW01A/xqxDrrjspnuhCcCHrh8J+fXUlLVOslZUoFTQZxJAfq9lMlJmdk1MNUiU2MgGrCJyXyIy2Vj1nvXyoKKiSe20jKSeKPdvNE3DkrLPrYeoE8Bxni9+HLXJwT8OdT8Q2fB+2M8f2hYUbTAQX+n4mfAONduGi523T3OZM0cc1qYe/1THZJtyFGWPLyZLyuy5QtXPW0T0PATJTrgkfWD7U1yvQEM6y0riNJkFlx+qZSkV3L9MaYoAK4Q3MFWw9Agz5bR/I22idH4Tw0L8eXOyi6bsuyvnIosQTLcqZi6bTw0UTwb1x4XR6uOFEcOeDcOqi6dnRNLCjKZowmrZdH4ALHblL90GTkgsG5D4EkUN3Jroo+o/o0ABdKzly/ySHQ5scnpIcHi46R+7SQDcpuXC45hy4C+PcpODiATizt/RZZfa6OfVMLua6xzumE5lJwJOBrHvoSvSdFAZkuazMTax0fd2AHoYfwp2Uqf4cC6Z6BtWRE1hkAfchQpAGVAwPlhB+CwUFS9P6yDPmdbZfvsLxXnfguMpHYmT7SICjgY90v+0cOkn0Bk4yspbdt0LXni0PD5Lo2m8JoOp3wczC7HZhs8jehc2OnKE530KtI3/ohnGeiww3XS50X7xdnjICoOGmK0D9e7pOytE4ULElZ2VWjUcC93I/Gz+Kj9bpCP63ernrbP/bfLPQ+/8/4Pu/7ZpRk5owEMc/jY/tAAE9H+/sXduZdqYz15m2jxFWSC8QJ8RT++mbwAJGvKt6Sl/Cg5J/NgnZX5JN0BGZ5ZuPki6zryIBPgq8ZDMiH0ZBMPan+tMI21oIxiikkiW15HfCI/sDKHqorlgCpWWohOCKLW0xFkUBsbI0KqVY22YLwe1WlzSFnvAYU95Xf7BEZaj6ntdlfAKWZtj0TYQZcxo/pVKsCmxvFJBFddXZOW3qQvsyo4lY70jkfkRmUghV3+WbGXDj2sZtdbmHF3Lb55ZQqGMKBPgYatt0HRLtCUwKqTKRioLy+069q7oHpgJPpzKVc33r61vYMPXTyO8jTP3CnFJRqW4NGC0UooBGe2CcY0VQJI1FzGlZsrgW0cRU8xuU2uJooSsltNQ94hchlm1zUjzBTHAhq04Rr7ranIYp0cpCFAqr9MeYPlSydpTxzouuRqkUKxmjVYSDl8oUGquOs54+IHJQcqttJHCq2LNdPcWBnLZ2HUx9gzwPsyXXYRs4uC/DnQ7ENrwO24lj+8rE9QeCi20/U77CSttw0fG2aa4zpuBxSavHX+uYbBNuw4yx5XQO/K4NVI3PWrrHIQiMyzXhHcuH6joBDeUsLcyw0SRAtqyeQSrYvE6rjwELhDfoK9x6+ATT6y6QN9E62wnhofd2cGMXTa86KacHJiUZaFJOXDQdHm4wENwbF06HhxsOBHfaC6cumh4dTX07mgYDRtOm6R1woSN37j5oUHJ+j9w7P3LojkQXRf8RXdBD10iO3D/JkdAmR4YkR/qTzpE7N9ANSi7szzkH7sw4Nyi4/puaz7pjevtapGa3m2mHp5lpxKQkgP6qzHSC6l6XlPc4a0+oPZgWIcS2iwKlnneNX1lM+S1m5CxJqqPLodFjj68TBtBpB4c3sR6TvXc7UZ+1fwh2dAnY7u3O5c+I1oFwchj+0QdCLPpNMN1Kt5uaRPZuarI3GOpzKpbaGw/tYxw3RCYuBF9u2zvoSt5/SfA9A2kWbFp9JmyxgKongSdkotduc7Owl/IxzQ2+Yl4uW5e4pf2spb19SXOFpV0nu1/Y62ne/YuB3P8F7Zrfb5swEMf/mjx2Agz58dimzfawSZNSadujCw54dXBknCbZXz8DBwRMWpIQJk3mIYKvjQ33ufP5UEZovt5/FngTfeMBYSPHCvYj9DhynLE9U7+pcMgFZwxCKGiQS3YlLOkfAqIF6pYGJKl1lJwzSTd10edxTHxZ07AQfFfvtuKsPusGh0QTlj5muvqDBjIC1basquELoWEEU089aHjB/mso+DaG+UYOWmVH3rzGxVjQP4lwwHdHEnoaobngXOZn6/2csNS0hdny+xYnWsvnFiSWXW5w4DHkoXh1EihLwCUXMuIhjzF7qtSH7PVIOoClriK5ZurUVqdkT+XPVP7kwdUvaEkkFvI+BaOEmMek0BaUMRiIxEHRw2c4Saifi9AlHeY3kfIA3oK3kiupesSvnG/K6QR/JXPOuMheClnZUbYUTJFSVjyWMKQ9huu2O3NDpdY5aWqQEr4VPvTywHmxCEnRq+KswofwNZHioPoIwrCkb/XhMThyWParYKoT4NnOFt2GrWPgnoY7G4itexu2E8P2ncC1B4ILc79htoVBy3RR8a7T3EVUkuUGZ4+/Uzm5TrhMM2lfhl8IeygTVWGzkm43BE5qckX4qOciO85AgxkN49RtFAkiSlZvREiyf5+WjgFucKdgK9h62Aiud1UiL7J1dJTCXet6cGOTTW8alLOWoEQDBeXEZNPh4ToDwZ2adDo8XHcguDMtnZps2jmb2vVs6gyYTYupj8C5htyl+6BBydkauTvbM+g6ovO8f4jO0dAVkiH3ITnk1smhIckhPegMuUsT3aDkXD3mDLgL89yg4PQvNQ+CYDXv3YKKRKqmZ4HV6yWYaUDVK8sGtRoK4HNsc5A0M6YGpD5m99CwpkGQ1ShtblJ3pDM85bwK4SqoY6vxEWesQ7XbqHp9UDWfcfovBmuV36QdfufKD279zmksj7ZNE6++bZo0nCEvSOGuhj+Uj9HNRSYm1/a3vx1yyXb0olKP9ragO7lOK2u9TD3Xuy6SGpxWU5/4/hkRphv7A2MW2pVB19w32c0V+ETQ6QM1v9s3B8pXkD6i19HLU+MDV/hAs+rRsnBnH2h+bbqhD+h1rvGBK3ygTLbFmn6pD2gl9A19QK+Yl+n+K7OQIJo//G879sWivx07avC3kafldLfF/VAfOV2vn58jEhuMF2BsFF7OkBj1atpgvAyjthoXBUv/GNVl9XfFfBGu/hKKnv4C7Zpfk5owEMA/jY/XAQKoj1fvbB/amc5cZ9o+5iBCepE4IZ7aT98ACwjRk0PNzTjwIGTzl/3tZpPICM2W2y8Cr+LvPCRs5FjhdoQeRo7j21P1mwl2hcDxQRAJGhYiuxY80X8EhBZI1zQkaaOg5JxJumoKA54kJJANGRaCb5rFFpw1e13hiGiCpwAzXfqLhjIGqW1ZdcZXQqMYup54kPGMg5dI8HUC/Y0ctMivInuJy7agfBrjkG/2ROhxhGaCc1k8LbczwjLVlmor6s2P5FbjFiSRXSo4MAy5K1+dhEoTkORCxjziCWaPtfRz/noka8BSqVgumXq01SPZUvk7E3/yIPUHclKJhbzPwChBwhNSyuaUMWiIJGFZImA4TWlQCKFI1sxfIuUOrAWvJVeieojfOF9V3Qn+QmaccZG/FLLyq8opmSIlWfBEQpO2D+lDNQtFZdo5qmoQpXwtAijlgfFiEZGyVM1ZuQ/hSyLFTpURhGFJX5vNYzDkqCpXw1QPwPMwW3Qdts4A9zjcqSG27nXYjge2bziubQgu9P2K2RoarcJFzbtJcxNTSZ5WOB/+RsXkJuEqzGRlGX4m7HMVqEqdVXS7IXAylSvCeyXn+fUONJjRKMnMRpEgomL1SoQk27dp6RiggjsBXcHSw0aQ3tSBvIzW8V4Id63zwflDNL2qU04POCUy5JTjIZqah+sYgjsZwql5uK4huFMtnA7RtHM0tZvR1DEYTcuu98C5A7m+6yCj5GyN3J3tDeg6ovO8D0TnaOhK0UDuJDnkNskhk+SQ7nQDub6Bzig5V/e5AVzPOGcUnH5S80BWMr6bU5FKlfFTYPVyKWYaTvXCssWsAQLo7GscRJoSM/XRALN7yFjSMMx3KIeMpGlG77CT9+0PzkLqO60jHNfTkNqHmHqXYDoc4lx+K9jY940Pw++874OqPzhN5N6iaew1F03jljEU21Go1bKHahjdTGQ8RNrLrW6NTtgTjZzu7Yec7ug8rbT1PPFc7zxPanFaTAISBP097Mix2QkFl7IzHdGdtmZvv5sj6h7tn2ioeOeLeLR+RnSLdnFk5jVjF147qve2i1MGdjm7KId8a3bxYXNDeRhbfRfk9rOBdkMIuVezAX2RfxM20O003pBdtKZ6p+/c0G6oWlxcwS7827SLD4sP1qXiQ6shbeV4QRvQdwJZyFD1LLhla7Hsfgd3u7i5kJ0fi5f5wxFB9yOC9v9Sjn5EUP2BdOYRgUrWH2QWRlJ/9Ioe/wM=7ZnNcpswEICfhkl76SCBMD7GTpwe2l5yaHtUQAE1MvLIcmz36bsCgcEijRP/5AIHBu2uQOy32hXCC6bzzZ2ii/y7TJnwsJ9uvODGwzjGBM5GsK0EAYkrQaZ4WonQTnDP/zIr9K10xVO27BhqKYXmi64wkUXBEt2RUaXkumv2KEX3qQuaMUdwn1DhSn/yVOdWinx/p/jKeJbbR8fEKh5o8pQpuSrs8zwcPJZHpZ7T+l7WfpnTVK5bouDWC6ZKSl1dzTdTJoxra7dV/WYvaJtxK1boQzrgqsMzFStWj7gcl97Wvijfhhl73wsm65xrdr+gidGuAT7Icj0X0EJw2byPsRX0gYlJ45GpFFKBqpAFM6ZaySdWC8FRfnk0mtrx4JPJIxeiZTkrDyOXhbbRgyLb7rsjFTwrQJaAWxgoJ/a1mdJs86LrUAME4pzJOdNqCya2A44sQxvjKA6q9roVMTXnvBUsyLdOpjZKs+beO1JwYWH1gwsccKiWDexeZzciXXbjscNu3IMuIMeTQ8TBxFLIPrYplc5lJgsqbnfSSRdkCxrbcP2rdf3bmHyB14NmASP7ZbuUjUpJSkxU6WuTKdtQQTbjZuC2S1pbJIIulzyphNbEPPEP03prIdKVliDajf+blIs6tA6Ml+D1uJjNbM/Ki8Z1/w8C8LRcqcRahbaaUJWxZj72x4pigmr+3L39MeSbpH9G8nggfzj56ELgQydZJzkXKQzXIxOP3Ax5+515GwfhxfI2cSD+gGWvgw5eTu/x6Tjdkmh714ochxlXcViUXlvFnKdpmRP6AqIbMm+IiUN5lnb2Pf1TsIzjbg2OkMMyIi7LOosewzIalr3vxUb8vWVv6GI737J35IALSTSwO5Qd2lv2ktHF0mc81MAzQRzji0EcDzXwpDWQ4L0aiNzv0HPVwHqvbSiCxxdBPIouWAQRcsiN4vEA750JFF8wgSJ3w3UogyehGODLrWWQu/s61MFT1kFM3O/6s9VB95vijj/DfDTbR3OA6qdUUw/DjfxEMaqNCNp+wdbmXIL3aZGac2rOXJt9JmlOudElK1U6ojK+WsLFVT3rr7zyjxXdftzEj/FDEEWHTPyUsDgNP3jij8K92uu7ayYU9wTLODxBsLifMcD8k4mQzwPBdxLs/XPWR7Det3kDQWju/qaWutYf6+D2Hw==7ZlLc9sgEIB/jWbaS4eHkeVj7cTpoe0lh6ZHImGJBgkPxq/++oIEthTsxkls5yJPJha7i4D9VrsCR3hSbu4UnRc/ZMZEhEC2ifBNhFCCiPlvBdtGgEnSCHLFs0YE94J7/pc5IXDSJc/YomOopRSaz7vCVFYVS3VHRpWS667ZTIruqHOas0Bwn1IRSn/xTBdOCgHYK74xnhdu6IQ4xSNNn3Ill5UbL0J4Vn8adUn9vZz9oqCZXLdE+DbCEyWlbq7KzYQJ61rvtqbf9Ih2N2/FKn1KB9R0WFGxZH7G9bz01vuiXg2z9iDC43XBNbuf09Rq1wa+kRW6FKYFzeVuPdZW0EcmxjuPTKSQyqgqWTFrqpV8Yl5oHAXqz07jHW98Mp5xIVqW0/pj5bLSLnpg7NqH7kgFzysjS41bmFGO3bKZ0mxz1HVwB8TEOZMl02prTFwHFDuGLsZhgpv2uhUxnnPRChYInJOpi9J8d+89KXPhYB0GhwNw0Mt6di+zG5Iuu9EoYDc6gA6T95MbBJRYZpKPa0qlC5nLiorbvXTc5dhixjZcP7Suf1uTL2Z1plmZiT24LnWjUZKaElX6q02UbaZGNuV23q5L5i1SQRcLnjZCZ2JH/MO03jqGdKmlEe3n/13KuY+sE8MFvxwW06nr2XjRuu7/MWA8LZcqdVaOn1lqzrzVkVBRTFDNV93bvwc8HF2ePOrJn05+eCXwJMjVacFFZqYbkXFEbvq0/ca0jfDgamk7DiD+NG+9ATqzOP2MT8fpjkTbu04UOMy6ipt30q9OUfIsq3PCoYDohswrYuJUnrWdWyc4B8sk6ZbgGAYsYxKy9G9U72E57N9634qNANjFNgixXe6tNwnADUjcszuVHYy77Mjwaulz1NfAC0EcoatB9MczfRE8UxEk/rnwMGG4D71UEYSwr4Jvr4Ldsx80jK9YBWF4ajdMws1lD+9YBn22i7hmBg3P7fo6eBaKGF3vZQYO+jp45jrY3QwiEm7sL1YHw93gHV+Z59GeH5UGKsiophEyNwJCyic7nLYHUDQtzFf9+JpvObOnS4W1T5eqXjgCVR0VgFZZfa5UylXT3O51a66L3RjAjt/8edFHpYMEPeI4PiUdZIQl2eCD08EQPavIGIQVOTkQQqPBGUIo3Jc2sD9Zhp97iG+FCMI0cBCiP517BUTT3P/MWutaP2Xj238=7ZpNc5swEIZ/jSendgDxYR8TN24P7Uxncmh7VEABNTLyCDm2++srzAIGkYTYQGYy4uCBV1+wj3ZXAs/Qcr3/KvAm+cEjwmaOFe1n6MvMcXx7oX5z4VAIjg9CLGhUSHYt3NF/BEQL1C2NSNaoKDlnkm6aYsjTlISyoWEh+K5Z7YGz5qgbHBNNuAsx09VfNJIJqLZl1QXfCI0TGHruQcE9Dh9jwbcpjDdz0MPxKIrXuOwL6mcJjvjuREK3M7QUnMvibL1fEpabtjRb0W71TGl134Kksk8DB25DHspHJ5GyBFxyIRMe8xSz21q9OT4eyTuw1FUi10yd2uqU7Kn8ncufPbj6AyWZxEJe52CUkPKUlNqKMgYdkTQqa4QMZxkNCxGq5N38JVIeYLbgreRKqm/xO+ebajjBH8mSMy6OD4Ws41GVlEyRUh54KqFL24frrpaFoXLrPGtqkDK+FSHU8mDyYhGTslbNWbkP4WsixUHVEYRhSZ+a3WOYyHFVr4apToBnN1s0DlvHwH0e7mIitu44bAPD9gXHtSeCC2M/YbaFTqt0UfNu0twlVJK7DT7e/k7l5CbhKs3kdRm+J+ymSlSlzSq6/RA4uckV4ZOaq+PxBjSY0TjNp40iQUTF6okISfYv09IxQAN3DraCpYeN4HpXJ/IyWycnKdy1Lgfnm2w6qlMuOpwSTeSUgcmm08N1JoI7N+l0erjuRHAXWjo12bR3NrWb2dSZMJuWQ5+Acw25c9dBk5KzNXKfbM+g64nO894RnaOhKyVD7lVyyG2SQ1OSQ7rTGXLnJrpJybm6zxlwZ+a5ScGZDf/w24bGHiHoZt97jwBNf3KqRqkTbOA1E2zQmgzF1gVateZDdRv9pkhgovJwK6EpndvRo/JH4rZajcjNd19fwSK7A5w/BDj9/bmKjPig0VPPJ1uIGnYHGKcGBkmzWW4tGmJ2DQVrGkXHaN81J5qz5g3T4m3B9iKCQTtE2jpBtwOgMwBAVwd4lV19JOcbNWj6fsv53A7nGyloeiZoDhY0bb9n0BwEnO5zS2Vj9XCZiZsXxE27w/nGipuerzE070t7e5/X9j6vV9REA4Dz9U2CIdeb3HzR2iR0LFVG++I/18iZVze9XW7xji5nvgoOB65rhTmWx5WvasxXwbOWJz32BqORM18FL0pzaDJ06rL+C3rx0rP+mz+6/Q8=7ZpBk5owFMc/jbOndoAIq8eu3W0P7Wk70/aYhSfQjcQJcdV++ibwArLBWWoVZzrh4CT/hEDeL88/QSdksdp9EnSdfeUJsEngJbsJ+TgJgsifq08t7GshiFBIRZ7Ukt8Kj/lvQNFDdZMnUHY6Ss6ZzNddMeZFAbHsaFQIvu12W3LWveqapmAJjzFltvo9T2SGqu95bcNnyNMMLz0LseGJxs+p4JsCrzcJyLI66uYVNWNh/zKjCd8eSOR+QhaCc1mXVrsFMB1aE7b6vIcjrc19CyjkkBMCvA25N1OHREUCq1zIjKe8oOy+Ve+q6YEewFO1TK6YKvqqCLtc/tDy+xBrP7GllFTIDxqMEgpegNEecsZwICgS0yNmtCzzuBaxix7mF0i5x9VCN5Irqb3FL5yvm8sJ/gwLzrioJkW86mhaDFOilCUvJA7pR1jvO7MOlI5OJ9Ql34gYpRBXKhUpmDXp2UT8hrNKH+ArkGKvughgVOYv3eEpLuS06dfCVAXk2c+WXIZt4OAiyPn12E4vw/bWsTUge75Kx4KLt/NC2QYHbeyi5d2luc1yCY9rWs1oqzy5S7ixGd2X0Sdgd41RmZg1dIchCHTIFeGDng/V8RdoKMvTQi8bFWIQDasXEBJ2Rx3tCAbz7GFihY8efoT1bWvkxq2zAwufev8OLnJuer6knPckJbleUt46N70w3OB6cGfOTi8Md3o9uHPLTp2bDnXTMOy6aTCim5q90wG4qSN36nPQqOR8i9w7P3TohqKbXxFdYKEzkiP3JrnprEuOjEmO2EnnyJ1qdKOSm9o558Cd6HOjgrvIptCU9aah3vz/v9sGi3N3J+H3vJkL+5fD2bcNvv0a7psAUMpCx9cl6MAEJd6rF3KhnaB+0JOh0TkyNLIgSkHVfEoNUg2X8cShPBVls0V7C+VZvmxnFsob/UPpjcM39Ol0wKvxc+FT1fZX7Krt4J8C5P4P7ZtLc5swEIB/jWfSQzMgmYePTZq0h3amMzm0PSpGwTQy8shy7PTXV8AKkEUmxDFwqDh40EpakL5dVi/P8PX68EWQzeo7TyibIS85zPDnGUIxCtRvIXiuBDiIK0EqsqQS+Y3gLvtLQeiBdJcldGsUlJwzmW1M4ZLnOV1KQ0aE4Huz2ANn5lM3JKWW4G5JmC39mSVyBVLf85qMrzRLV/DoOICMe7J8TAXf5fC8GcIP5VVlr4nWBeW3K5LwfUuEb2b4WnAuq7v14Zqyomt1t1X1bl/Ird9b0Fz2qYDgNeSzbjpNVE9Akgu54inPCbtppFdl82ihwFOplVwzdeurW3rI5K9CfBlA6jfkbCUR8lMBRglynlMtu80YA0U0T3SJJSPbbbashFCkUPOHSvkM1kJ2kitR84rfON/UjxP8kV5zxkXZKOyVV52jmWIleeC5BJV+COmumlVHFb1jdPWW78QSRGD0ql0p1Tbp2UT8mrNyH8rXVIpnVURQRmT2ZKonYMhpXa6BqW6AZzdbPAxb5OACyMV0bOfDsI0cWw2y41M6Flx4nSfCdqC0DhcNb5PmfpVJerchZYv2KiabhOswU5Rl5J6yqzpQ6T6r6fZDgIouV4RbJW/L6w1oCMvSvDAb1cVU1KyeqJD08GJEewEDVEAh9BUMPXwM6X0TyHW0XrVC+Nx7P7jQRdPzOeWiwynxdE4ZuWg6MFw0HdzYhdOB4c6ng7uwwqmLpn2jqb8woykaMZrquVML3NyRO3UcNCo53yL30Q8cup7oMJ4QHbLQaZEj9/rnEpnk8JjksO10jtypgW5UcnPb5xy4E+PcqODslRopKL2Ugqg2benV7cVFzhP6QZUps0OyLkilsmy7N4vUb8iKVJI9qVvIgGL5/XZTFSyUXCZEkqISuip1ecX4qKp8L1p1LXXR5w+tHNUm81md0iPjU3jkkYUZZgO21LYPEGnkjD4UGgrU2ZKwTyBeZ0lSzqa6DNo0+TfY9NvmMu8yv7lvmp8f2eZXTzja9hefw/7cgtM7p63GHDXqDb/3HBWq/uCZ0tgM8ILAHOBFR8ZQzaah1pE91K/Rz0QiNyo430h81OCycM59vjUphGyHRwM4fF+6HWtQbj35zHjDCfHaA3i3onxmvPGEeO1VEmw7tIuq3VE1OoqqY27RDnUq5j/1y9D2Sw1zEr8c6FzM/xpVO/BOeeoJ2XsILqqe2XsnPPek36e9Duqiat+oGk644YfsVYbAkTt1PDQqudgi99Ht1PYlF3sTkrPPtehpiSP3Krlgwv0+/agWOfsAmgPXL8yNCs4+1+LbCz2OXL8wNyo5+8vopv0n75ThAc5hd++U1f8kHH6nDNvnZ9xX+dSB0Ki+bR+fsZ29y+dePM4wqCP16NRXOk3L3ulb8+PBa9jPtyxFQfyKourbcYKTqmTzX9iqePN/Y3zzDw==7Zldb5swFIZ/TW4nwAGSyzZNt0mLWqnTPi5dcMCrY0fGaZL9+hk4mDgQlaxj3MBFZF5/AOc59ovJBC02h48Sb9OViAmbeE58mKC7iecF7lz/5sKxFLwAhETSuJTcWniivwmIDqg7GpPMaqiEYIpubTESnJNIWRqWUuztZmvB7KtucUIawlOEWVP9TmOVguo6Tl3xidAkhUvPfKh4xtFLIsWOw/UmHloXR1m9wdVY0D5LcSz2JxJaTtBCCqHK0uawICwPbRW2st/9hVpz35Jw1aWDB7ehjtWjk1hHAk6FVKlIBMdsWau3xeORfABHn6Vqw3TR1UVyoOpHLn/w4ewn1GQKS3WTg9ECF5xU2j1lDAYiPK5aRAxnGY1KEZrkw/wiSh0hW/BOCS3Vt/hFiK25nBQvZCGYkMVDIac4TE3FFGllLbiCId0Aztt6loHKo2OFOhM7GYHkQ6ZimZAqJ50mEddw1tOHiA1R8qibSMKwoq/28BgSOTHtapi6ADzb2aJ+2HojXAA5H47ttB+24ci2AtmylP4vuHA7r5jtYNDF8qEB3Ma5T6kiT1tcPNJem7KN2PhM3pbhZ8JujVNVQTN4uzHw8phrxCct74vjCjaY0YTneaNjTKSB9UqkIoeLlnaBA3TwfYgfvHu4lTfvayefgZSeePjUeT+5YLTTfzcr5y2zEg03K8PRTnuG6w0Hdzb6ac9wp8PBnTf99Ovop139dBo6lp96LX7q9+Sn1fbpFN1qRNf5VWhIdG4T3cOIriu6YDYgOq+B7tujPl/yhHJCJOXJyLEjR4RsjqiF47wvjqid42e+lliHbxepnSQjyq5GOH0bpev2xXLazvKOZPmTjgz/zhHbGAZ9IfQbmMavA1ftMawNRdCZfecNBXR9FFSPaHImdOwPSma9roYotz7Q6ywfzG10S5GgMcsfpYj1Qq3FFeY40RNhnOsdX6GCAa03bL795t9wdUen2HwWhVVVeIBC8zXLqOembSoqB8iFt5NFh1OdZYSFGdif8gSpgSiHQyPMbqBiQ+O4WLPaUtBO0iuy8Lol410JE55vl4IWgw9bMsa7PmP0af0vb7lS1P+ko+Uf7Zpdk5owFIZ/jZfdAQKKl7vuRy/amc7YmbaXWYiQbiROiKv21zfACV/RHXZUvAk3kpOEwHlezgvqBC3W+xeBN+l3HhM28Zx4P0GPE89z1aY+isihigRoVgUSQWMY1ASW9B+BoAPRLY1J3hkoOWeSbrrBiGcZiWQnhoXgu+6wFWfdVTc4IUZgGWFmRn/RWKb6uhyn6fhKaJLC0mEAHa84eksE32aw3sRDq3KrutdYHwvG5ymO+a4VQk8TtBCcy2pvvV8QVuRWp62a93yitz5vQTI5ZAJgyeVBXzqJVSagyYVMecIzzJ6a6EN5eaQ4gKNaqVwzteuqXbKn8ncRvvMCaP6BrlxiIe8LMiqQ8Yzo2DNlDI5EsliPiBjOcxpVQRhSHOYvkfIAcsFbyVWoOcdvnG/q5QR/IwvOuCivCjnlVvdoqEhFVjyTcEh3Cu1jM83UQrZzvhURZG8OYsUiIXqUV8WKxLbmAY8XwtdEioMaIAjDkr53JYhByUk9rqGpdgDocbjhdeDOLNwGrn8ruHAy75hte8WzxbtLc5dSSZYbXF7PTlXuLuG6FhVjGX4l7KGuZjpnNd1hCLwi5Ypwa+RzuX0CDWY0yQrZKDREfMTqnQhJ9h9igF5f5wr8SS1XtXdNtdclPW3Ved85H5yuBy1yFtxQcCjogkPuiOB885bzLLmht9zshuQC+5hzthN2bG92aduDqT84Vcs2ogm9u6Arm6Cnh8qgYV5PEvWJDFPJ1D4vXVYl4TgqCZzZiCqZmS7gGsKxLnDCBfyeC8xHdIHQIGefvAaTC5wbkptb/75oZdaxa1dmNB3Rv4/czNa/z1LJxb+5OqGScET/ritf4wJfrH8Pfv/2bucCWo4tcuZ7nQV3Alx4Q3DI2vdlC3MwTmEO3L59++h6hdm39n1ZlUxHUgnq2/c1VRIYJuCaP2JaFxj2JWzdHsMFpga5ufleZ8mdeP1GNyRnfuX1QDNcnt6SYBGlauenIMSgqS5O9pB1OACcdsIhZOSwSBWNMLuHjjWN49ICjmmkq6JPyOTsAjycqNf7KatG1SLqHyHqfZ6oajZ/KamKbvO/HfT0Hw==7ZfBcpswEIafhmsGEGD7WDtxe+nJh54VWIPGAnkUudh9+qzEgiHgqZNh2os52NK/Kwn934oBj23K83fNj8VPlYH0Qj87e+zZC8MkWOGvFS6NECYk5FpkjRRchZ34AyT6pJ5EBm+DRKOUNOI4FFNVVZCagca1VvUwba/kcNUjz2Ek7FIux+ovkZmC1MD3r4EfIPKCll7GFHjl6SHX6lTRel7I9u5qwiVv56L8t4Jnqu5J7MVjG62UaVrleQPSWtva1ozb3oh2962hMvcMCJsBv7k8QXvH7r7MpfXC7QZsvu+xdV0IA7sjT220RvioFaaU2Auw2e3H5kr+CnLdObJRUmkMVaoCm2q0OkArolG+u7pIazx6st4LKXuZW3dZXVWGqidIqD81I5cir1BL0RbA4Jq2DdrA+aZ1QQcE6xxUCUZfMIUGREtiSDUeRNSvexXTci56xbIijVOR5t3UV1DYIFbT3NiIW9MMtxk3HP8OcHmQnJNkNEEynoFkNCIpYW8e7L7KbjVmt5hAF82ALh6h026BB7v72MXx/2OX3HqA4twJLy2U3Lht+vY8PlH0A1ncu/mAb8CEQPXNJ2nkp3VS4BvINwqUIsvsMpP1MqyoT5TMvbhnoMsW8YBumNz5VA1nwLv4O15JeN2ZffD9/Old/ju+2L2+E7tY77uDvbwD7ZpNj5swEIZ/TY5dAeYjHLtp0h5aqdIe2h694IC7BkeOs0n662tggIBJRZVALuYQ4fEX8TOed2RYoFV2+izwLv3GY8IWjhWfFujTwnGWjqd+C8O5MiBvWRkSQePKZLeGF/qHgNEC64HGZN9pKDlnku66xojnOYlkx4aF4Mdusy1n3Vl3OCGa4SXCTLf+oLFMwWpbVlvxhdAkhamXHlS84ugtEfyQw3wLB23Lq6rOcD0WtN+nOObHCxNaL9BKcC6ru+y0IqxY2nrZqn6bK7XNcwuSyzEdHHgMea7/OonVSkCRC5nyhOeYrVvrc/n3SDGApUqpzJi6tdUtOVH5szA/Kf5V8RdU7SUW8mNBRhlynpPatqGMwUgkj+sWEcP7PY0qIzQphvlNpDyDu+CD5MrUPuNXznfNdIK/kRVnXJT/Clnl1dTUUJGybHkuYUjbh/JQz2qliuW5utZg2vODiKCVC96LRUKglddwVtuH8IxIcVZNBGFY0vfu6BgcOWnatTDVDfAcZoumYRsYttfZ+jOxhanfMTv0QucF7i7MY0olednh8umPKmx3ATeRqGjL8Cthz00sq5esgTuOgFOsuAJ80XJTXv9BBjOa5IXXKBBENKjeiZDk9G9YOgbo4NVhHNSpWbtjG+vrgJ5eRHnXuh2cp4Ez3MZyc90et3A+br6+4XTtNOCubDj/ceACk+HcXwUvJS+8UfKg63dO1SStywTOk9dxGoR63lBJMfTrOUTzIKN8ZGkypWl9xLamcZIwmM9JQl0BbM1vjAJcUQDUVQAUzKcAdXZ3Qc4kXePJhQ8kp28wI973DcxoksDsejOq90AibuT7vl7iTuMlwYzyjULjJdMeh9lI9xx0a3wZLRVIE/kPJj0bfbJiP1Dk9bNM14AbCy54IDjPZGcT624wie76Vj87a/b/BNmZb3R3Yi9ZTuMlTj87m9JLAk0EbP3k1qjAuPN115tRBZYauVBPtQ25YXK+8zhySE+ZByTdkBv3MnJWcvqey/BJGcp7y3wKMJpi4HUlzkE6xXCAYv0e/6ZvOPRz6YzmBt3Y0Nl/qTyALrgPOlVsP8mrspv2s0e0/gs=7ZnBcpswEIafhsmpGUBg3GPjxO2hnelMDm2OCmxAjYw8Qo7tPn0FLGAhu4OT2p5M4WCj1UqI/XZ/hO2Q2WLzWdJl9k0kwB3fTTYOuXV8Pwo8/VkatrWBhNPakEqW1CavM9yz34BGF60rlkBhOCohuGJL0xiLPIdYGTYqpVibbk+Cm1dd0hQsw31MuW39wRKVodVz3a7jC7A0w0tPQ+x4pPFzKsUqx+s5Pnmqjrp7QZu50L/IaCLWOyZy55CZFELVZ4vNDHgZ2iZs9bj5gd523RJyNWSAj8tQ2+bWIdGRwKaQKhOpyCm/66w31e1BOYGrW5lacH3q6VPYMPWzNF/7ITYfsKtQVKpPJRltyEUOjW3OOMeZIE8aj5jTomBxbUSXcppfoNQW04WulNCmbo1fhVi2l5PiGWaCC1ndFXGro+1poBJteRK5wim9Cbb3jawjVYbHiHUhVjJGU4CpSmUKGP7QJuK1nHX5gFiAklvtIoFTxV7M2Skmctr6dTD1CfLcz5achm00skWQk8uxxdW8UL7qSecObhPmOmMK7pe0uqG1lm0TcKtEpS+nj8BvWi1rQtbCHUbALyOuAe94zqvjCDKUszQvs0aHGGSL6gWkgs1B0TuAAQeETVXi08mLMHbrTusbQc92VD5w3w4utMCFI7eB3IKJya2FdAZuTbGfXE11LOS27gub5gPO8E6Udnq80lpJYIrvxBbfum7OILUTW2rHkh0stdPLlaznWZjGze1xZblbcB7599sdHPpdMD1jp/NRdN1Lm4+9fKjFAcf1UqJdyLAsOdEr0H+0TTayJLhclpDodFlCrKfAuN8evG8jPU7kjA8B+03Jfi8ewR0A1xQUggu8M2647foadfn1unwE/LfqcnBGXW6Wt1PeH8bd+eD6di9Y3/YT9VZAUaZtxqovCeBUP/EryvLW03evyJVD5u8W8t/ejk8BOfJNyL5rQ/aCPZT7VfsqyvbvXePGaTC6SQ/dCTdOutn961QLcffPHrn7Aw== \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/09/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/09/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/09/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/09/diagrams.xml new file mode 100644 index 0000000..657f03c --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/09/diagrams.xml @@ -0,0 +1 @@ +7VlNk6IwEP01lLcpIaLOcXR19rB78rC7xwy0kDUSK8Sv/fWbQIcPYabckdULHCzyuoHwXufRKR0y355eJd3F30UI3PGG4ckhXxzPm/iu/jXAOQeIP82BSLIwh9wSWLE/gOAQ0T0LIa0lKiG4Yrs6GIgkgUDVMCqlONbT1oLXn7qjETSAVUB5E/3BQhUj6g6HZeArsCjGR099DLzRYBNJsU/weY5H1tmRh7fU3gvz05iG4liByMIhcymEys+2pzlwQ62lLb9u+U60mLeERF1zgZdfcKB8D3bG2bzU2XKRvQ2Y/KFDZseYKVjtaGCiRy2+xmK15Xrk6tPifUwup2/AZwUjc8GF1KFEJGBSlRQbsKAmapgdRcQSrzmZrRnnlcxldhhcJAqrxx3juO2OlLMo0VigaQEdnDV5QuoOIBWcKhDy9gpiC0qedQpGiS1WrHF3jONjWTHkGbG4UixFIsUqjYp7l0rpExSrXTjSEE7FLH2Cg36htKGhfiV1IVSNfZSkSjNCDeYMQUyvlBcMbFkYmse0Vka9dv6hOK4VtgMdR9abrI5k0tCxTUavAxWnDaUg1EaEQyFVLCKRUL4o0QtOK5LCiamflfNfJuXJz8SmUr0YX6wuP40tmZladiNIQpsRcJqmLMhBTDE3/Q1KnVEVuldCQ+UUvwmxa62t91c26ULoVOxlgOSN8FNBZQSY5eeQofXDYpDAqWKHuv/fIu2osUAHAWfBZtAb7LUG610Y7KRpsNOWhTnqYGH6DfW05XHzde/lu9pXHyffuJfvVvl88jj5Jr18t8o3vuxO7yjfc9/VdNnVWCWrbY3rPqqvsbOpNjax0IXZNzafbWyKrcQd1qYtnN5bu+ts7qrfqDfXTs3VbzHX8cPMtbnvGBhdem/9tLfese9x+21H9956T/36fUfn28b/qJ8eln+UZLHKn1Fk8Rc=jZNLb4MwDIB/DXdIVNYdRx/rZadO2jkFF6IGXKWhwH79HDCltKq0HJDz+YntBHJVtp9WnYsvzMAEIszaQK4DIRaxpK8H3QBE/D6A3OpsQNEE9voXGIZMa53BZWboEI3T5zlMsaogdTOmrMVmbnZEM896Vjk8gX2qzDP90ZkrmEZhOCl2oPOCUy8XrDio9JRbrCvOFwh57M+gLtUYi+0vhcqwuUNyE8iVRXSDVLYrML61Y9sGv+0L7a1uC5X7j4MYHK7K1PzrOypHhA3W1DIRdlj7McJF5xUJ3412Dmwgt1y+68aWOWgpY1K40hCISLw4iydYoUFyWFdYkWVy1MY8IGV8cLlOqWYfO7mCdZqG8cGKUmeZT5M0hXawP6vU52xo84j1zQb/O6HPOfbTX4w6gEluE3msBCvHmydivo8mNLawP8S5Q1QTtC+7HN1mR08CsARnOzJhBxkvBhd+DtGSx99MyyXfmBV3exUzU7zP+S30NFMSeKzjdVqfXnf3ROXmDw==7ZdNc5swEIZ/DdNbB5A/6LF27ObQ9uLM9KzAGjQWkkcIY/fXdyUkDMHJJG7rkzkw4t3V1z67AgKyLI/fFN0XP2QGPIjD7BiQhyCO59MI70Y4tQKZJq2QK5a1UnQWNuw3ODF0as0yqAaOWkqu2X4oplIISPVAo0rJZui2lXw4657mMBI2KeVj9RfLdOHUKAzPhkdgeeGmTqbO8EzTXa5kLdx8QUy29mrNJfVjOf+qoJlsehJZBWSppNRtqzwugZvQ+rC1/davWLt1KxD6PR0mbYcD5bXb+lMBCoxHhTch8absPjGwompAfXYL1ycfLLtdMAOGAVk0BdOw2dPUWBvMDtQKXXJ8irDZbdj4cvoMfNGFbCm5VGgSUoBx1UruwIsYydBencWTwaAttozznufaXkaXQrv0ihL3fGlEylkuUEsxboDGhYsLKA3HV2MbdcSwEECWoNUJXVwHMp+2XVwRRMRBb84pRXziFL1smrh+1GVx3g19JokNB/My2OkI7CNOgMp3ONha/Sk1VthLlrhb/QLYgIJD0w+3k0YRNLFjWFJfnaFkWWamuZghwxz6QJL0AMezNwD/A56TSTjkGY55doXd5+m1v+E5G/Fc4WbM6piJ94EB1qZdi+0Gx705F3FOcwqz7RbsLn0R32v42hpOotvV8HzEfC3TuvKHc13VlHOzWCnMC7Iwx3ZGtUFetm/kO+WrKMckvh3lZET5QYpPplZLXD6zbCusZrZlqcEMaSEwLjm7cHzfAb8TcHJDwF/GgBVtLLjafxjeGX6YISHkdgz9j0kPYhDPuPlWYtjITeOJ8p0XcbxOvxO+lnAy+W+E8fH8l2VtvT9ZsvoD7VdRb5swEP41eZ0ILk322KbJVmmTJmXStkcHLuDVcMiYkOzX7wwHhNJWXabkKTyA/fl8Z9/nz8YTsUj3n4zMk68YgZ74XrSfiIeJ78+CKb0dcGgAEcwbIDYqaqBpD6zVH2DQY7RUERQDQ4uorcqHYIhZBqEdYNIYrIZmW9TDqLmMYQSsQ6nH6A8V2YTRqef1DZ9BxQmHngfcsJHhU2ywzDjexBfb+mmaU9n6YvsikRFWR5BYTsTCINqmlO4XoF1q27Q1/VavtHbjNpDZ93S44WHYQzt1iCgTXEVjE4wxk3rZo/f19MA58KiW2FRTcUpF2Cv708EfAq794pbCSmPvHDEEZJhBi62U1uwIsqi1CLUsChU2IJs4N7/B2gOvFllaJKgf4hfEvAtn8AkWqNHUkxJe/XQtLaeCkC1mll1O51x/qWeTKJedV1PNUIGlCdnK58UrTQxsJTqaST2AKVhzIBMDWlq1G3qXvI7jzq7nkgpM58vUcuid1CU7fYxoqGrron2vkN4LNECfFUhbGtLb87UwZLpKlIV1Luu5VaT7IfvdUna2Wm5A33diaBPaUf8+fnzHB9F/ZLmqn3/gTWoVZ25N0dzBdETuwFjYv03lmCTucNPuU7y9TVs5V/1m4bd7RXK0T9x6/8/r7VWyZ5WsGEs2uJBkxUiy35CyutFOpY9priGlkVNMzK5aPVGr3T/GJbQ6v2r1rFoNxlqdXUirwVvHq6T/P9+7iyI6VelY9R7UdqvCkn5gr6fsycoV3gWVOxvRu0Zdup23qC8UxnFIFwaVxVdCTyX04/kIpWp/i6rbjm6qYvkX7Zxdc5s4FIZ/jS/rAWT8cZm49XZ3mp3Opju5VkA2agAxQg52f/1KWGBASkocgXe38oVjjkDIeo7OKx3kTMA6OfxGYRbdkRDFE88JDxPwceJ5K8fl78JwPBlmwDkZdhSHJ5N7NtzjH0gaq9P2OER560RGSMxw1jYGJE1RwFo2SCkp2qdtSdy+awZ3SDHcBzBWrQ84ZJG0uo5zLviM8C6St176suARBk87SvapvN/EA9vydSpOYFWXPD+PYEiKhgl8moA1JYSdPiWHNYpF11bddrpu80Jp3W6KUtbnAv90wTOM96hqcdkudqz6ImeUPNXd4E7Abd1ohx+EMI9QKA9gjHcp/xzw2yPKDRFL4vNVmagyOeyEz0wTEjztsylHyCBOEc2njwIcog84Lau/pdIxRM1bHMdrEhNaNqrqVF5r2bpGybx88ZKE1/oNHU7dsBbVoWBPc/yM/kL5ueISVv0FYviI4tsaYlVvSlIkGsHbKtvkLuVx49ZO+eJ22amIMnR4EYxb4+ajCJEEMXrkp8gLvLn0EDmCVpJUcXbH+UyeEjU8sR5pUA6BXV312Q34B+kJeq+YK17xVQwYrxrWV/EOmAaR6OkWhYVKoXaA6nYx2rK+UPxXoXSYuJ7CxHU1TKr+fA+ShYIkYkxEwxtRhbcpimIaUlhMMfk3MGoN3avxckEbWMWvAczzBwK2/HlkbYeeIsIM3WcwEKUF72Cl88/IXg9TSkysA1PbEzw1rm7K1xtCneIvJrAtO+NsqeG28FVucwOxz3V7SKIcCDgp5xFNTOKLYz6RuJH9wkjWsH4R3L6SHDNMROkjYYwkLwNtKl15s5s8O813yr6vDrb4INzoVrbnYzs0BGHqTDEfpVsurIjy8ZpwawgZ5H+EPed/t4hPTThAb7Pizr/xVy7vzQ8RguEH11tOs3SnaGXLI//7Pue3fU4juEATKkzIbaUjDZf7OxcsOm7HytlMKyi0er2apTS6V5qUHuu6aYLDUNxGG4VewT7ifOl1fvWM+tjh2eCnmy95JvgBhd/vYsUS4fRJtPD4w6J8B8p6VdicZzma8G+E5czqtindrgfcKLrdZylrdfv/rtueP6Juq+tkq9vvDfazEXVbXVRb3TaIcjGmbtv1tjHdBs6Yur2yum112wPueLpdxRur2+aCPXDG021PTdFZ3TaIEoyo21W0t7ptQLd1zzeG0m1PTXpZ3f4FdXsxom6ruTmr2+8N9vMRdVtN0VndNohyNaZuq7kvq9s/A1c9m9I80NBu5jGi02qS6zOvxcLqK3jdPT9qvKy3BbYEzzfATk1q3fFaUpZbfH3xuf4V+am5rT8Jw1suQ2Jiayle/HRfR1G39c4ERaCmi+5QnvMlhAXYFyAA8+sNQ9BjS5cF10v+tHsxPA0318TcBajJoW+84SHmq2y7UnhD+Lze3iigSxMBmGWxjZ6DD8KZCYC6DVGAUJha/bucoD8mQd3OKBCQJNvz72cZXspQl24ZjKEu3QK+w2eYBxRnzEK8DKL2WddgENVUjOXWk9ts1Rl9mufN+omoa2IFoSZiHiIyEb9K5W8bEsccg52RvgHnEnSmpDMVp+45kpE5qZqWuYn5V7FjceCxaCKIztRszBdIZR2W3gX0NDtuh6OnpmL+wOIMC+8yeJql/HDwNOmYAiE7+exLz+/8HnnILCg/PP8bibKs8a86wKd/AA==7ZfBcpswEIafhskVLDt2j7UTN5ee3JmcFViDxkJihFzsPn13YcEQkowzSdwezAGLf1fI2u+XNARilR9+OFlkP20COpiEySEQd8FkMp9FeCfh2AhitmiE1KmkkaKTsFF/gMWQ1b1KoBwkemu1V8VQjK0xEPuBJp2z1TBta/Vw1EKmMBI2sdRj9VElPmM1CsNT4AFUmvHQixkHnmS8S53dGx4vmIhtfTXhXLbv4vwyk4mtepK4D8TKWeubVn5YgabStmVr+q1fiXb/24Hx53SYNB1+S73nqf+qALwyKf8/f2xrUs8KqF8YiGWVKQ+bQsYUrdAEqGU+1/gUYbObF+Vq+QR62VVmZbV1GDLWAKV6Z3fQiliwsL66SAsAa7PcKq17mev6It0azy6KFvz80hulVqlBLcbyAAaXPH1wHg6vljDqwKDfwebg3RFTuIOYM0v2etR6oeo5p+Wd9Uxzy5pks6bdq0/AsMHMXuYnRvzWgIyu7M5jdxv+Q3bTEbsHLDvtdPXGULcVzRXKZkGGntZmScP6Oq/Au93SBkfQxXrEHSvjn8EdEGOMfTQsjapNdVa4Q37nQK6ShIZ50U1Dv73DUOea4RPYz56t225P7rNffBH72Vvsc7kDamd0v8FpI2kV39CQeK6QNA1znKWyhsTyWHrIyyv/d+7b0yF/EV6Q//wt/iovNBBgbDvgRX+l+zG6iwvS/XZd3f8d/0uu7vYzpmeAx6w+sxML9fndHub4q63d0Y+qbaFM54275RX6x6B/5ZGOj6fPtDrW+xQW938B7VVNb5wwEP013AGHdHMsbNJeqh5WUc8OzIIVYyPjDWx/fccw5mPZSBspudUHZL8Ze4b3niFgWd3/MLypfukCZBCHRR+wfRDH35IInw44jwBLdiNQGlGMUDQDB/EXCAwJPYkC2lWi1Vpa0azBXCsFuV1h3BjdrdOOWq6rNryEDXDIudyif0RhK0KjMJwDP0GUFZXeJRR44flrafRJUb0gZsdhjOGa+7Mov614obsFxB4Dlhmt7Tir+wyko9bTNu57eic69W1A2Vs2xOOGNy5P9OqOBaHKgTWDz+cWTEvN2rMnyEKP56eVrSUCEU5ba/QrZFriLrZXWmFmehRSXkB4eqlwmWOHgHj6BsYKLPqdArUoClcm7Sph4dDw3NXs0GeIDdSCaz50NT17biH5C8h04v+yE60s+Sza0dqnoEjhMHwevSex6RqE/l2Co0k2vA2ga7DmjCm04e6OlKabEHundLOvJjdUC0t5jJOVy+noWU6ckKLX1WUbdTOeV4O6F3queb3G/FLq22lfu2JJ9Bjxtyu+MAtmPg3jA9JtnPUZ8iXJWr7dVr7o4Yp8958gX7KRbw+N1OfaNR+HvxsrtNrezf9a3qYlu/86LXE5f8SH2OJHyR7/AQ==7ZdNc5swEIZ/DdcOIBP7Gjt2e2hOnk7bowxrUCNYj1h/9ddXguVrSDJuOnYv1oGRXq1W0j7SavDEIj99NnKXPWMC2gv95OSJJy8Mp1Fgv04414KIZrWQGpXUUtAJa/UbWPRZ3asEyoEhIWpSu6EYY1FATANNGoPHodkW9XDWnUxhJKxjqcfqd5VQxmrg+13HF1BpxlPPIu7YyPglNbgveD4vFNuq1N25bHyxfZnJBI89SSw9sTCIVNfy0wK0C20Ttnrc6o3edt0GCrpkQMTLoHOzdUhsJLiJhjJMsZB62anzanvgHPi2lVGubTWwVTgp+tGr/3QmnyLbKkkaenRgrFRgAY22UlqzIyiSxiLWsixVXIts4pz+AqIznxa5J7RSt8SviDu2K8ngCyxQo6k2JfyqtD0NU2GVLRbELoMZt18bWQfKRefNULNU4t7EbBXy4ZUmBbaatJjt7QHMgczZmhjQktRh6F3yOU5bu46lrTDO19E+XANtjbOBG9zRDtCKG6HlqQ9S79npGswBzIj4kOcxUwTrnax2cLSJe8i4zUXOVssN6HmbzZqwtYAvoxC6qFvIPctVVf6CjtQqLdzJsTDsFhtcdrsEp/eBjVHwACE4//L7FDbtYy/bNzk66yX6B//f6YkRvSdJciNLuPP7ID8xuSG/yYjfM+RYLW9NaO4UL6UYhf/xFs7uz+NVn8fp+HkMb/Q8TkcX9FvpHkf/cb64X84PptjgipfTNrtfnqqv91spln8A7VlNk5swDP01XDuAQxKOTTZpD9tTptPu0QEF6DooY5yv/voakPkYNp1tWsihcMhYT7KM9fxGBCy23F8+SX6Iv2AIwnLt8GKxJ8t1fdvRvzlwLYEJs0sgkklYQk4NbJKfQKAJOyYhZK1AhShUcmiDAaYpBKqFcSnx3A7boWiveuARdIBNwEUX/ZaEKibUse3a8RmSKKal5x45tjx4jSQeU1rPctmuuEr3nptcFJ/FPMRzA2Iriy0loipH+8sSRF5aU7Zy3vqGt7pvCal6zwRGt6GuZusQ6kqQiVLFGGHKxapGF8X2IE9gaytWe6GHjh7CJVHfc/iDR9YLeTLFpfqYE6OBFFMw2DoRghJBGpqIQPAsS4ISpJA8zQ9Q6kqnhR8Vaqi+xWfEQ7WcxFdYokBZbIrZxVV5DKdMIztMFaV05mS/NbMsVF6dm6UmKMOjDChqQoeXywgoyqto1uoB3IOSVx0iQXCVnNrZOZ3jqIqrudQDovPGWXD64dYdyb1Nrj8UuW4/5M5Gcm+T69gDsUtrn7g4UtJn5KFGFlzwNADZIb9N7TlOFGwOvNjLWXfoNt1V08ljBd+CWFRtyxSwovp9fLh5/TXdjch1cf0BT1wkUZqfIU2L3qIh7gRSweX31HU5oQkTnxotPYg4xj432rppxnGjo0/tfyDS+dhde9Wo94ZGpwNp1OtodAPyNErzbmkye0BpzkZl9qrMeVeZk4GEOe8I82s2yvJuWQ7aMAeSpS6FvDb/zeT2C2X4bzXrP7Cb+mM3/TvZMu+B3dTx+9Ft51VDQ7izUbhGuOat6UOUaxYfpXuvdKfskdKdduh74opveQYjgXc+Mk2c/gjUZv11oPA1vsCw1S8=7ZZNb6MwEIZ/DXeDk6h7XLJtc6m0UlrtceXCBKwaGxlTYH/9jrH5CqnUVm1P9cHC74yZYZ4xENB90d5qVuZ3KgURRCRtA/oriKJd+ANnK3ROiHZeyDRPnRROwpH/Ay8Sr9Y8hWrhaJQShpdLMVFSQmIWGtNaNUu3kxLLqCXLYCUcEybW6h+emtyrISGT4QA8y33oq603PLLkKdOqlj5eENFTP5y5YMO9vH+Vs1Q1M4leB3SvlTLuqmj3IGxph7K5fTcvWMe8NUjzmg2R2/DMRO0f/YDp2GrjdAsG5wOI0idruqFABlq8f5ybQqAQ4mVltHqCvRJKoyKVRM/4xIU4k5jgmcRlghkC6vEzaMOx9D+9oeBpasPETc4NHEuW2JgN9hlqfWnBJk9szKF6diHYI4h4rP95Jkoa32fhlV8PLgiJ9GPw88/pq2kThPbFAocjNjwNoAowukMXv2FDt25LN/aQWzdTX2F4p+Wzlho6ivlWzsZbTzjxwhO9TJeu6P5WlWWqZH94al2BPaW8Suqq4lY947ys9yUi8xZ4PY5lt8wBOMtw6qKzJkLPm368Aemq4z4EK1li3V3AurmAdfcBWDdrrHf25QID2YcUiu6b5TtZjsfxK1huVyzvG+jfuxYnbifBBiHCX/uhxCf+hvo+qJR8HlRcTl/s3jb7K6LX/wE= \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/10/.gitkeep b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/10/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/10/diagrams.xml b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/10/diagrams.xml new file mode 100644 index 0000000..0273620 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/diagrams/10/diagrams.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/index.js new file mode 100644 index 0000000..f57259d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/index.js @@ -0,0 +1,48 @@ +// --- Directions +// Check to see if two provided strings are anagrams of eachother. +// One string is an anagram of another if it uses the same characters +// in the same quantity. Only consider characters, not spaces +// or punctuation. Consider capital letters to be the same as lower case +// --- Examples +// anagrams('rail safety', 'fairy tales') --> True +// anagrams('RAIL! SAFETY!', 'fairy tales') --> True +// anagrams('Hi there', 'Bye there') --> False + +// function anagrams(stringA, stringB) { +// const aCharMap = buildCharMap(stringA); +// const bCharMap = buildCharMap(stringB); + +// if(Object.keys(aCharMap).length !== Object.keys(bCharMap).length) { +// return false; +// } + +// for (let char in aCharMap) { +// if (aCharMap[char] !== bCharMap[char]){ +// return false; +// } +// } + +// return true; +// } + + +// function buildCharMap(str){ +// const charMap = {}; + +// for (let char of str.replace(/[^\w]/g, "").toLowerCase()) { +// charMap[char] = charMap[char] + 1 || 1; +// } +// return charMap; +// } + +function anagrams(stringA, stringB){ + return cleanString(stringA) === cleanString(stringB); +} + +function cleanString(str){ + return str.replace(/[^\w]/g, "").toLowerCase().split("").sort().join(""); +} + + + +module.exports = anagrams; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/test.js new file mode 100644 index 0000000..60f117b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/anagrams/test.js @@ -0,0 +1,27 @@ +const anagrams = require('./index.js'); + +test('anagrams function exists', () => { + expect(typeof anagrams).toEqual('function'); +}); + +test('"hello" is an anagram of "llohe"', () => { + expect(anagrams('hello', 'llohe')).toBeTruthy(); +}); + +test('"Whoa! Hi!" is an anagram of "Hi! Whoa!"', () => { + expect(anagrams('Whoa! Hi!', 'Hi! Whoa!')).toBeTruthy(); +}); + +test('"One One" is not an anagram of "Two two two"', () => { + expect(anagrams('One One', 'Two two two')).toBeFalsy(); +}); + +test('"One one" is not an anagram of "One one c"', () => { + expect(anagrams('One one', 'One one c')).toBeFalsy(); +}); + +test('"A tree, a life, a bench" is not an anagram of "A tree, a fence, a yard"', () => { + expect( + anagrams('A tree, a life, a bench', 'A tree, a fence, a yard') + ).toBeFalsy(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/index.js new file mode 100644 index 0000000..ceec26c --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/index.js @@ -0,0 +1,52 @@ +// --- Directions +// 1) Implement the Node class to create +// a binary search tree. The constructor +// should initialize values 'data', 'left', +// and 'right'. +// 2) Implement the 'insert' method for the +// Node class. Insert should accept an argument +// 'data', then create an insert a new node +// at the appropriate location in the tree. +// 3) Implement the 'contains' method for the Node +// class. Contains should accept a 'data' argument +// and return the Node in the tree with the same value. + +class Node { + constructor(data) { + this.data = data; + this.left = null; + this.right = null; + } + + insert(data){ + // handle less than current node w. left child + if(data < this.data && this.left){ + this.left.insert(data) + // handle less than current node w/o left + } else if (data < this.data) { + this.left = new Node(data) + + // handle greater than current node w. right child + }else if(data > this.data && this.right) { + this.right.insert(data); + // handle greater than current node w/o right + } else if(data > this.data){ + this.right = new Node(data) + } + } + + contains(data){ + if(this.data === data){ + return this; + } + + if (this.data < data && this.right){ + return this.right.contains(data); + } else if (this.data > data && this.left){ + return this.left.contains(data) + } + return null; + } +} + +module.exports = Node; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/test.js new file mode 100644 index 0000000..331ae22 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/bst/test.js @@ -0,0 +1,41 @@ +const Node = require('./index'); + +test('Node is a constructor', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); +}); + +test('Node can insert correctly', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(17); + + expect(node.left.data).toEqual(5); + expect(node.right.data).toEqual(15); + expect(node.right.right.data).toEqual(17); +}); + +test('Contains returns node with the same data', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(20); + node.insert(0); + node.insert(-5); + node.insert(3); + + const three = node.left.left.right; + expect(node.contains(3)).toEqual(three); +}); + +test('Contains returns null if value not found', () => { + const node = new Node(10); + node.insert(5); + node.insert(15); + node.insert(20); + node.insert(0); + node.insert(-5); + node.insert(3); + + expect(node.contains(9999)).toEqual(null); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/index.js new file mode 100644 index 0000000..c3b36b6 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/index.js @@ -0,0 +1,39 @@ +// --- Directions +// Write a function that accepts a string. The function should +// capitalize the first letter of each word in the string then +// return the capitalized string. +// --- Examples +// capitalize('a short sentence') --> 'A Short Sentence' +// capitalize('a lazy fox') --> 'A Lazy Fox' +// capitalize('look, it is working!') --> 'Look, It Is Working!' + +// function capitalize(str) { +// const words = []; + +// for (let word of str.split(' ')) { +// words.push(word[0].toUpperCase() + word.slice(1)); +// } + +// return words.join(' '); +// } + + +function capitalize(str){ + + let result = str[0].toUpperCase(); + + for (let i = 1; i < str.length; i++) { + if(str[i - 1] === ' '){ + result += str[i].toUpperCase(); + } else { + result += str[i] + } + } + return result; +} + + + + + +module.exports = capitalize; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/test.js new file mode 100644 index 0000000..21a2423 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/capitalize/test.js @@ -0,0 +1,17 @@ +const capitalize = require('./index'); + +test('Capitalize is a function', () => { + expect(typeof capitalize).toEqual('function'); +}); + +test('capitalizes the first letter of every word in a sentence', () => { + expect(capitalize('hi there, how is it going?')).toEqual( + 'Hi There, How Is It Going?' + ); +}); + +test('capitalizes the first letter', () => { + expect(capitalize('i love breakfast at bill miller bbq')).toEqual( + 'I Love Breakfast At Bill Miller Bbq' + ); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/index.js new file mode 100644 index 0000000..e98891b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/index.js @@ -0,0 +1,39 @@ +// --- Directions +// Given an array and chunk size, divide the array into many subarrays +// where each subarray is of length size +// --- Examples +// chunk([1, 2, 3, 4], 2) --> [[ 1, 2], [3, 4]] +// chunk([1, 2, 3, 4, 5], 2) --> [[ 1, 2], [3, 4], [5]] +// chunk([1, 2, 3, 4, 5, 6, 7, 8], 3) --> [[ 1, 2, 3], [4, 5, 6], [7, 8]] +// chunk([1, 2, 3, 4, 5], 4) --> [[ 1, 2, 3, 4], [5]] +// chunk([1, 2, 3, 4, 5], 10) --> [[ 1, 2, 3, 4, 5]] + +// function chunk(array, size) { +// const chunked = []; + +// for(let element of array) { +// const last = chunked[chunked.length - 1]; + +// if(!last || last.length === size) { +// chunked.push([element]); +// } else { +// last.push(element); +// } +// } + +// return chunked; +// } + + +function chunk(array, size) { + const chunked = []; + let index = 0; + + while (index < array.length) { + chunked.push(array.slice(index, index + size)); + index += size; + } + return chunked; +} + +module.exports = chunk; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/test.js new file mode 100644 index 0000000..ef3d645 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/chunk/test.js @@ -0,0 +1,33 @@ +const chunk = require('./index'); + +test('function chunk exists', () => { + expect(typeof chunk).toEqual('function'); +}); + +test('chunk divides an array of 10 elements with chunk size 2', () => { + const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + const chunked = chunk(arr, 2); + + expect(chunked).toEqual([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]); +}); + +test('chunk divides an array of 3 elements with chunk size 1', () => { + const arr = [1, 2, 3]; + const chunked = chunk(arr, 1); + + expect(chunked).toEqual([[1], [2], [3]]); +}); + +test('chunk divides an array of 5 elements with chunk size 3', () => { + const arr = [1, 2, 3, 4, 5]; + const chunked = chunk(arr, 3); + + expect(chunked).toEqual([[1, 2, 3], [4, 5]]); +}); + +test('chunk divides an array of 13 elements with chunk size 5', () => { + const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + const chunked = chunk(arr, 5); + + expect(chunked).toEqual([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13]]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/index.js new file mode 100644 index 0000000..15e4cb7 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/index.js @@ -0,0 +1,31 @@ +// --- Directions +// Given a linked list, return true if the list +// is circular, false if it is not. +// --- Examples +// const l = new List(); +// const a = new Node('a'); +// const b = new Node('b'); +// const c = new Node('c'); +// l.head = a; +// a.next = b; +// b.next = c; +// c.next = b; +// circular(l) // true + +function circular(list) { + let slow = list.getFirst(); + let fast = list.getFirst(); + + while(fast && fast.next && fast.next.next){ + slow = slow.next; + fast = fast.next.next; + + if(slow === fast){ + return true; + } + } + + return false; +} + +module.exports = circular; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/linkedlist.js new file mode 100644 index 0000000..b7da56b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/linkedlist.js @@ -0,0 +1,178 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor(values = []) { + this.head = null; + + for (let value of values) { + this.insertLast(value); + } + } + + clear() { + this.head = null; + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getAt(index) { + if (!this.head) { + return null; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + node = node.next; + counter++; + } + return null; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + let counter = 1; + let previous = this.head; + let node = this.head.next; + while (node) { + if (counter === index) { + previous.next = new Node(data, node); + return; + } + previous = node; + node = node.next; + counter++; + } + + previous.next = new Node(data, node); + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index - 1) { + if (node.next) { + return (node.next = node.next.next); + } else { + return (node.next = null); + } + } + node = node.next; + counter++; + } + } + + getFirst() { + return this.head; + } + + insertFirst(data) { + this.head = new Node(data, this.getFirst()); + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node.next) { + node = node.next; + } + + return node; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + last.next = new Node(data); + return last.next; + } else { + this.head = new Node(data); + return this.head; + } + } + + forEach(fn) { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + fn(node); + node = node.next; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/test.js new file mode 100644 index 0000000..7cb50b2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/circular/test.js @@ -0,0 +1,50 @@ +const circular = require('./index'); +const L = require('./linkedlist'); +const List = L.LinkedList; +const Node = L.Node; + +test('circular', () => { + expect(typeof circular).toEqual('function'); +}); + +test('circular detects circular linked lists', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = b; + + expect(circular(l)).toEqual(true); +}); + +test('circular detects circular linked lists linked at the head', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = a; + + expect(circular(l)).toEqual(true); +}); + +test('circular detects non-circular linked lists', () => { + const l = new List(); + const a = new Node('a'); + const b = new Node('b'); + const c = new Node('c'); + + l.head = a; + a.next = b; + b.next = c; + c.next = null; + + expect(circular(l)).toEqual(false); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/example.html b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/example.html new file mode 100644 index 0000000..f87a916 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/example.html @@ -0,0 +1,15 @@ + + + + +

Click the button

+ + + diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/index.js new file mode 100644 index 0000000..23352db --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/index.js @@ -0,0 +1,37 @@ +// --- Directions +// Create an 'eventing' library out of the +// Events class. The Events class should +// have methods 'on', 'trigger', and 'off'. + +class Events { + // Register an event handler + constructor() { + this.events = {}; + } + // Register an event handler + on(eventName, callback) { + if (this.events[eventName]) { + this.events[eventName].push(callback); + } else { + this.events[eventName] = [callback]; + } + } + + // Trigger all callbacks associated + // with a given eventName + trigger(eventName) { + if (this.events[eventName]){ + for (let callback of this.events[eventName]){ + callback(); + } + } + } + + // Remove all event handlers associated + // with the given eventName + off(eventName) { + delete this.events[eventName]; + } +} + +module.exports = Events; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/test.js new file mode 100644 index 0000000..e015819 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/events/test.js @@ -0,0 +1,77 @@ +const Events = require('./index'); + +test('Events can be registered then triggered', () => { + const events = new Events(); + + const cb1 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(1); +}); + +test('Multiple events can be registered then triggered', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.on('click', cb2); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(1); + expect(cb2.mock.calls.length).toBe(1); +}); + +test('Events can be triggered multiple times', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + events.on('click', cb2); + events.trigger('click'); + events.trigger('click'); + + expect(cb1.mock.calls.length).toBe(3); + expect(cb2.mock.calls.length).toBe(2); +}); + +test('Events can have different names', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('click', cb1); + events.trigger('click'); + events.on('hover', cb2); + events.trigger('click'); + events.trigger('hover'); + + expect(cb1.mock.calls.length).toBe(2); + expect(cb2.mock.calls.length).toBe(1); +}); + +test('Events can be toggled off', () => { + const events = new Events(); + + const cb1 = jest.fn(); + const cb2 = jest.fn(); + + events.on('hover', cb2); + + events.on('click', cb1); + events.trigger('click'); + events.off('click'); + events.trigger('click'); + + events.trigger('hover'); + + expect(cb1.mock.calls.length).toBe(1); + expect(cb2.mock.calls.length).toBe(1); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/index.js new file mode 100644 index 0000000..16b1451 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/index.js @@ -0,0 +1,56 @@ +// --- Directions +// Print out the n-th entry in the fibonacci series. +// The fibonacci series is an ordering of numbers where +// each number is the sum of the preceeding two. +// For example, the sequence +// [0, 1, 1, 2, 3, 5, 8, 13, 21, 34] +// forms the first ten entries of the fibonacci series. +// Example: +// fib(4) === 3 + +// recursive solution: exponential runtime +function slowFib(n) { + if(n < 2) return n; + return fib(n -1) + fib(n-2); +} + +// memoize: constant time +function memoize(fn) { + const cache = {}; + + return function(...args) { + if(cache[args]){ + return cache[args]; + } + + const result = fn.apply(this, args); + cache[args] = result; + + return result; + } +} + +// // iterative solution: linear runtime +// function fib(n) { +// const result = [0, 1]; + +// for(let i = 2; i <= n; i++) { +// const a = result[i - 1]; +// const b = result[i - 2]; + +// result.push(a + b); +// } +// return result[n]; +// } + + + +const fib = memoize(slowFib); + + + + + + + +module.exports = fib; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/test.js new file mode 100644 index 0000000..02a385d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fib/test.js @@ -0,0 +1,25 @@ +const fib = require('./index'); + +test('Fib function is defined', () => { + expect(typeof fib).toEqual('function'); +}); + +test('calculates correct fib value for 1', () => { + expect(fib(1)).toEqual(1); +}); + +test('calculates correct fib value for 2', () => { + expect(fib(2)).toEqual(1); +}); + +test('calculates correct fib value for 3', () => { + expect(fib(3)).toEqual(2); +}); + +test('calculates correct fib value for 4', () => { + expect(fib(4)).toEqual(3); +}); + +test('calculates correct fib value for 15', () => { + expect(fib(39)).toEqual(63245986); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/index.js new file mode 100644 index 0000000..f7e12d9 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/index.js @@ -0,0 +1,26 @@ +// --- Directions +// Write a program that console logs the numbers +// from 1 to n. But for multiples of three print +// “fizz” instead of the number and for the multiples +// of five print “buzz”. For numbers which are multiples +// of both three and five print “fizzbuzz”. +// --- Example +// fizzBuzz(5); +// 1 +// 2 +// fizz +// 4 +// buzz + +function fizzBuzz(n) { + for(let i = 1; i <= n; i++){ + if (i % 15 === 0){ + console.log("fizzbuzz"); + } else if (i % 3 === 0) { + console.log("fizz"); + } else if (i % 5 === 0) { + console.log("buzz"); + } else console.log(i); + } +} +module.exports = fizzBuzz; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/test.js new file mode 100644 index 0000000..b25dc82 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fizzbuzz/test.js @@ -0,0 +1,39 @@ +const fizzBuzz = require('./index'); + +test('fizzBuzz function is defined', () => { + expect(fizzBuzz).toBeDefined(); +}); + +test('Calling fizzbuzz with `5` prints out 5 statements', () => { + fizzBuzz(5); + + expect(console.log.mock.calls.length).toEqual(5); +}); + +test('Calling fizzbuzz with 15 prints out the correct values', () => { + fizzBuzz(15); + + expect(console.log.mock.calls[0][0]).toEqual(1); + expect(console.log.mock.calls[1][0]).toEqual(2); + expect(console.log.mock.calls[2][0]).toEqual('fizz'); + expect(console.log.mock.calls[3][0]).toEqual(4); + expect(console.log.mock.calls[4][0]).toEqual('buzz'); + expect(console.log.mock.calls[5][0]).toEqual('fizz'); + expect(console.log.mock.calls[6][0]).toEqual(7); + expect(console.log.mock.calls[7][0]).toEqual(8); + expect(console.log.mock.calls[8][0]).toEqual('fizz'); + expect(console.log.mock.calls[9][0]).toEqual('buzz'); + expect(console.log.mock.calls[10][0]).toEqual(11); + expect(console.log.mock.calls[11][0]).toEqual('fizz'); + expect(console.log.mock.calls[12][0]).toEqual(13); + expect(console.log.mock.calls[13][0]).toEqual(14); + expect(console.log.mock.calls[14][0]).toEqual('fizzbuzz'); +}); + +beforeEach(() => { + jest.spyOn(console, 'log'); +}); + +afterEach(() => { + console.log.mockRestore(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/index.js new file mode 100644 index 0000000..b62c92b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/index.js @@ -0,0 +1,30 @@ +// --- Directions +// Given a linked list, return the element n spaces +// from the last node in the list. Do not call the 'size' +// method of the linked list. Assume that n will always +// be less than the length of the list. +// --- Examples +// const list = new List(); +// list.insertLast('a'); +// list.insertLast('b'); +// list.insertLast('c'); +// list.insertLast('d'); +// fromLast(list, 2).data // 'b' + +function fromLast(list, n) { + let fast = list.getFirst(); + let slow = list.getFirst(); + + while(n > 0){ + fast = fast.next; + n--; + } + + while(fast.next){ + slow = slow.next; + fast = fast.next; + } + return slow; +} + +module.exports = fromLast; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/linkedlist.js new file mode 100644 index 0000000..2029b3b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/linkedlist.js @@ -0,0 +1,156 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor() { + this.head = null; + } + + insertFirst(data) { + this.head = new Node(data, this.head); + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getFirst() { + return this.head; + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + if (!node.next) { + return node; + } + node = node.next; + } + } + + clear() { + this.head = null; + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + // There are some existing nodes in our chain + last.next = new Node(data); + } else { + // The chain is empty! + this.head = new Node(data); + } + } + + getAt(index) { + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + + counter++; + node = node.next; + } + return null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + if (index === 0) { + this.head = this.head.next; + return; + } + + const previous = this.getAt(index - 1); + if (!previous || !previous.next) { + return; + } + previous.next = previous.next.next; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + const previous = this.getAt(index - 1) || this.getLast(); + const node = new Node(data, previous.next); + previous.next = node; + } + + forEach(fn) { + let node = this.head; + let counter = 0; + while (node) { + fn(node, counter); + node = node.next; + counter++; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/test.js new file mode 100644 index 0000000..e4684d5 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/fromlast/test.js @@ -0,0 +1,20 @@ +const fromLast = require('./index'); +const L = require('./linkedlist'); +const List = L.LinkedList; +const Node = L.Node; + +test('fromLast is a function', () => { + expect(typeof fromLast).toEqual('function'); +}); + +test('fromLast returns the node n elements from the end', () => { + const l = new List(); + + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertLast('e'); + + expect(fromLast(l, 3).data).toEqual('b'); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/index.js new file mode 100644 index 0000000..5bc0c06 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/index.js @@ -0,0 +1,34 @@ +// --- Directions +// Given the root node of a tree, return +// an array where each element is the width +// of the tree at each level. +// --- Example +// Given: +// 0 +// / | \ +// 1 2 3 +// | | +// 4 5 +// Answer: [1, 3, 2] + +function levelWidth(root) { + const arr = [root, 's'] + const counters = [0] + + while(arr.length > 1) { + const node = arr.shift(); + + if(node === 's'){ + counters.push(0); + arr.push('s'); + + } else { + arr.push(...node.children); + counters[counters.length - 1]++; + } + + } + return counters; +} + +module.exports = levelWidth; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/node.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/node.js new file mode 100644 index 0000000..5238e8f --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/node.js @@ -0,0 +1,10 @@ +module.exports = class Node { + constructor(data) { + this.data = data; + this.children = []; + } + + add(data) { + this.children.push(new Node(data)); + } +}; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/test.js new file mode 100644 index 0000000..35d20c2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/levelwidth/test.js @@ -0,0 +1,27 @@ +const Node = require('./node'); +const levelWidth = require('./index'); + +test('levelWidth is a function', () => { + expect(typeof levelWidth).toEqual('function'); +}); + +test('levelWidth returns number of nodes at widest point', () => { + const root = new Node(0); + root.add(1); + root.add(2); + root.add(3); + root.children[0].add(4); + root.children[2].add(5); + + expect(levelWidth(root)).toEqual([1, 3, 2]); +}); + +test('levelWidth returns number of nodes at widest point', () => { + const root = new Node(0); + root.add(1); + root.children[0].add(2); + root.children[0].add(3); + root.children[0].children[0].add(4); + + expect(levelWidth(root)).toEqual([1, 1, 2, 1]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/directions.html b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/directions.html new file mode 100644 index 0000000..ecb118d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/directions.html @@ -0,0 +1,377 @@ + + + + + +

Node Class API

+ + + + + + + + + + + + + + + + + + + +
FunctionArgumentsReturnsDirectionsExample
Node.constructor(Data, Node)Node + Creates a class instance to represent a node. The node should + have two properties, 'data' and 'next'. Accept both + of these as arguments to the 'Node' constructor, then + assign them to the instance as properties 'data' and 'next'. + If 'next' is not provided to the constructor, then default its + value to be 'null'. + +
+            const n = new Node('There');
+            n.data // 'Hi'
+            n.next // null
+            const n2 = new Node('Hi', n);
+            n.next // returns n
+          
+
+ +

LinkedList Class API

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FunctionArgumentsReturnsDirectionsExample
constructor-(LinkedList) + Create a class to represent a linked list. When created, + a linked list should have *no* head node associated with it. + The LinkedList instance will have one property, 'head', which + is a reference to the first node of the linked list. By default + 'head' should be 'null'. + +
+            const list = new LinkedList();
+            list.head // null
+          
+
insertFirst(data)- + Creates a new Node from argument 'data' and assigns the resulting + node to the 'head' property. Make sure to handle the case in which + the linked list already has a node assigned to the 'head' property. + +
+            const list = new LinkedList();
+            list.insertFirst('Hi There'); // List has one node
+          
+
size-(integer) + Returns the number of nodes in the linked list. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.size(); // returns 3
+          
+
getFirst-(Node) + Returns the first node of the linked list. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.getFirst(); // returns Node instance with data 'a'
+          
+
+ getLast + + - + + (Node) + + Returns the last node of the linked list + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.getLast(); // returns node with data 'a'
+          
+
+ clear + + - + + - + + Empties the linked list of any nodes. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.clear();
+            list.size(); // returns 0
+          
+
+ removeFirst + + - + + - + + Removes only the first node of the linked list. The list's head should + now be the second element. + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.removeFirst();
+            list.getFirst(); // returns node with data 'a'
+          
+
+ removeLast + + - + + - + + Removes the last node of the chain + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.removeLast();
+            list.size(); // returns 1
+            list.getLast(); // returns node with data of 'b'
+          
+
+ insertLast + + (Data) + + - + + Inserts a new node with provided data at the end of the chain + +
+            const list = new LinkedList();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertLast('c');
+            list.getLast(); // returns node with data 'C'
+          
+
+ getAt + + (integer) + + (Node) + + Returns the node at the provided index + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.getAt(1); // returns node with data 'b'
+          
+
+ removeAt + + (integer) + + - + + Removes node at the provided index + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.removeAt(1);
+            list.getAt(1); // returns node with data 'a'
+          
+
+ insertAt + + (Data, integer) + + - + + Create an insert a new node at provided index. + If index is out of bounds, add the node to the end + of the list. + +
+            const list = new List();
+            list.insertFirst('a');
+            list.insertFirst('b');
+            list.insertFirst('c');
+            list.insertAt('Hi', 1)
+            list.getAt(1); // returns node with data 'Hi'
+          
+
+ forEach + + (function) + + - + + Calls the provided function with every node of the chain + +
+            const list = new List();
+
+            list.insertLast(1);
+            list.insertLast(2);
+            list.insertLast(3);
+            list.insertLast(4);
+
+            list.forEach(node => {
+              node.data += 10;
+            });
+            list.getAt(0); // Returns node with data '11'
+          
+
+ for...of Loop + + - + + - + + Linked list should be compatible as the subject of a 'for...of' loop + +
+            const list = new List();
+
+            list.insertLast(1);
+            list.insertLast(2);
+            list.insertLast(3);
+            list.insertLast(4);
+
+            for (let node of list) {
+              node.data += 10;
+            }
+
+            node.getAt(1); // returns node with data 11
+          
+
+ diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/index.js new file mode 100644 index 0000000..6edd76c --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/index.js @@ -0,0 +1,175 @@ +// --- Directions +// Implement classes Node and Linked Lists +// See 'directions' document + +class Node { + constructor(data, next){ + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor() { + this.head = null; + } + + insertAt(data, index) { + // if list is empty + if (!this.head) { + this.head = new Node(data); + return; + } + + // if inserting at first node + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + // if inserting later in list + const previous = this.getAt(index - 1) || this.getLast(); + const node = new Node(data, previous.next); + previous.next = node; + } + + + + insertFirst(data) { + this.head = new Node(data, this.head); + } + + insertLast(data) { + const last = this.getLast(); + + if(last) { + // last.next = new Node(data); + this.insertAt(data, last.next) + } else { + //this.head = new Node(data); + this.insertFirst(data); + } + } + + size(){ + let counter = 0; + let node = this.head; + while(node) { + counter++; + node = node.next; + } + return counter; + } + + getAt(index){ + if (!this.head){ + return null; + } + + let counter = 0; + let node = this.head; + while(node) { + if (counter === index) { + return node; + } + + counter++; + node = node.next; + } + return null; + } + + getFirst() { + // return this.head; + return this.getAt(0); + } + + getLast() { + // if(!this.head){ + // return null; + // } + + // let node = this.head; + // while(node){ + // if (!node.next){ + // return node; + // } + // node = node.next; + + // } + return this.getAt(this.size()- 1); + } + + clear() { + this.head = null; + } + + removeAt(index){ + if (!this.head){ + return; + } + + if (index === 0) { + this.head = this.head.next; + return; + } + + const previous = this.getAt(index - 1); + if(!previous || !previous.next) { + return; + } + previous.next = previous.next.next; + } + + removeFirst() { + // if(!this.head){ + // return null; + // } + + // this.head = this.head.next; + this.removeAt(0); + } + + removeLast(){ + // // for empty list + // if(!this.head){ + // return; + // } + + // // for list length one + // if(!this.head.next){ + // this.head = null; + // return; + // } + + // // for list longer than one + // let previous = this.head; + // let node = this.head.next; + // while(node.next){ + // previous = node; + // node = node.next + // } + // previous.next = null; + this.removeAt(this.size() - 1); + } + + forEach(fn) { + let node = this.head; + while(node){ + fn(node); + node = node.next; + } + } + + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/test.js new file mode 100644 index 0000000..f4de046 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/linkedlist/test.js @@ -0,0 +1,321 @@ +const L = require('./index'); +const List = L.LinkedList; +const Node = L.Node; + +test('List is a class', () => { + expect(typeof List.prototype.constructor).toEqual('function'); +}); + +test('Node is a class', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); +}); + +describe('A Node', () => { + test('has properties "data" and "next"', () => { + const node = new Node('a', 'b'); + expect(node.data).toEqual('a'); + expect(node.next).toEqual('b'); + }); +}); + +describe('Insert First', () => { + test('appends a node to the start of the list', () => { + const l = new List(); + l.insertFirst(1); + expect(l.head.data).toEqual(1); + l.insertFirst(2); + expect(l.head.data).toEqual(2); + }); +}); + +describe('Size', () => { + test('returns the number of items in the linked list', () => { + const l = new List(); + expect(l.size()).toEqual(0); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + expect(l.size()).toEqual(4); + }); +}); + +describe('GetFirst', () => { + test('returns the first element', () => { + const l = new List(); + l.insertFirst(1); + expect(l.getFirst().data).toEqual(1); + l.insertFirst(2); + expect(l.getFirst().data).toEqual(2); + }); +}); + +describe('GetLast', () => { + test('returns the last element', () => { + const l = new List(); + l.insertFirst(2); + expect(l.getLast()).toEqual({ data: 2, next: null }); + l.insertFirst(1); + expect(l.getLast()).toEqual({ data: 2, next: null }); + }); +}); + +describe('Clear', () => { + test('empties out the list', () => { + const l = new List(); + expect(l.size()).toEqual(0); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + l.insertFirst(1); + expect(l.size()).toEqual(4); + l.clear(); + expect(l.size()).toEqual(0); + }); +}); + +describe('RemoveFirst', () => { + test('removes the first node when the list has a size of one', () => { + const l = new List(); + l.insertFirst('a'); + l.removeFirst(); + expect(l.size()).toEqual(0); + expect(l.getFirst()).toEqual(null); + }); + + test('removes the first node when the list has a size of three', () => { + const l = new List(); + l.insertFirst('c'); + l.insertFirst('b'); + l.insertFirst('a'); + l.removeFirst(); + expect(l.size()).toEqual(2); + expect(l.getFirst().data).toEqual('b'); + l.removeFirst(); + expect(l.size()).toEqual(1); + expect(l.getFirst().data).toEqual('c'); + }); +}); + +describe('RemoveLast', () => { + test('RemoveLast removes the last node when list is empty', () => { + const l = new List(); + expect(() => { + l.removeLast(); + }).not.toThrow(); + }); + + test('RemoveLast removes the last node when list is length 1', () => { + const l = new List(); + l.insertFirst('a'); + l.removeLast(); + expect(l.head).toEqual(null); + }); + + test('RemoveLast removes the last node when list is length 2', () => { + const l = new List(); + l.insertFirst('b'); + l.insertFirst('a'); + + l.removeLast(); + + expect(l.size()).toEqual(1); + expect(l.head.data).toEqual('a'); + }); + + test('RemoveLast removes the last node when list is length 3', () => { + const l = new List(); + l.insertFirst('c'); + l.insertFirst('b'); + l.insertFirst('a'); + l.removeLast(); + + expect(l.size()).toEqual(2); + expect(l.getLast().data).toEqual('b'); + }); +}); + +describe('InsertLast', () => { + test('adds to the end of the list', () => { + const l = new List(); + l.insertFirst('a'); + + l.insertLast('b'); + + expect(l.size()).toEqual(2); + expect(l.getLast().data).toEqual('b'); + }); +}); + +describe('GetAt', () => { + test('returns the node at given index', () => { + const l = new List(); + expect(l.getAt(10)).toEqual(null); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + expect(l.getAt(0).data).toEqual(1); + expect(l.getAt(1).data).toEqual(2); + expect(l.getAt(2).data).toEqual(3); + expect(l.getAt(3).data).toEqual(4); + }); +}); + +describe('RemoveAt', () => { + test('removeAt doesnt crash on an empty list', () => { + const l = new List(); + expect(() => { + l.removeAt(0); + l.removeAt(1); + l.removeAt(2); + }).not.toThrow(); + }); + + test('removeAt doesnt crash on an index out of bounds', () => { + const l = new List(); + expect(() => { + const l = new List(); + l.insertFirst('a'); + l.removeAt(1); + }).not.toThrow(); + }); + + test('removeAt deletes the first node', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(0).data).toEqual(1); + l.removeAt(0); + expect(l.getAt(0).data).toEqual(2); + }); + + test('removeAt deletes the node at the given index', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(1).data).toEqual(2); + l.removeAt(1); + expect(l.getAt(1).data).toEqual(3); + }); + + test('removeAt works on the last node', () => { + const l = new List(); + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + expect(l.getAt(3).data).toEqual(4); + l.removeAt(3); + expect(l.getAt(3)).toEqual(null); + }); +}); + +describe('InsertAt', () => { + test('inserts a new node with data at the 0 index when the list is empty', () => { + const l = new List(); + l.insertAt('hi', 0); + expect(l.getFirst().data).toEqual('hi'); + }); + + test('inserts a new node with data at the 0 index when the list has elements', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertAt('hi', 0); + expect(l.getAt(0).data).toEqual('hi'); + expect(l.getAt(1).data).toEqual('a'); + expect(l.getAt(2).data).toEqual('b'); + expect(l.getAt(3).data).toEqual('c'); + }); + + test('inserts a new node with data at a middle index', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertAt('hi', 2); + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + expect(l.getAt(3).data).toEqual('c'); + expect(l.getAt(4).data).toEqual('d'); + }); + + test('inserts a new node with data at a last index', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertAt('hi', 2); + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + }); + + test('insert a new node when index is out of bounds', () => { + const l = new List(); + l.insertLast('a'); + l.insertLast('b'); + l.insertAt('hi', 30); + + expect(l.getAt(0).data).toEqual('a'); + expect(l.getAt(1).data).toEqual('b'); + expect(l.getAt(2).data).toEqual('hi'); + }); +}); + +describe('ForEach', () => { + test('applies a transform to each node', () => { + const l = new List(); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + l.forEach(node => { + node.data += 10; + }); + + expect(l.getAt(0).data).toEqual(11); + expect(l.getAt(1).data).toEqual(12); + expect(l.getAt(2).data).toEqual(13); + expect(l.getAt(3).data).toEqual(14); + }); +}); + +describe('for...of loops', () => { + test('works with the linked list', () => { + const l = new List(); + + l.insertLast(1); + l.insertLast(2); + l.insertLast(3); + l.insertLast(4); + + for (let node of l) { + node.data += 10; + } + + expect(l.getAt(0).data).toEqual(11); + expect(l.getAt(1).data).toEqual(12); + expect(l.getAt(2).data).toEqual(13); + expect(l.getAt(3).data).toEqual(14); + }); + + test('for...of works on an empty list', () => { + const l = new List(); + expect(() => { + for (let node of l) { + } + }).not.toThrow(); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/index.js new file mode 100644 index 0000000..257b5f5 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/index.js @@ -0,0 +1,64 @@ +// --- Directions +// Write a function that accepts an integer N +// and returns a NxN spiral matrix. +// --- Examples +// matrix(2) +// [[1, 2], +// [4, 3]] +// matrix(3) +// [[1, 2, 3], +// [8, 9, 4], +// [7, 6, 5]] +// matrix(4) +// [[1, 2, 3, 4], +// [12, 13, 14, 5], +// [11, 16, 15, 6], +// [10, 9, 8, 7]] + +function matrix(n) { + const results = []; + let counter = 1; + + for (let i = 0; i < n; i++) { + results.push([]); + } + + let start_col = 0; + let start_row = 0; + let end_col = n - 1; + let end_row = n - 1; + + while(start_col <= end_col && start_row <= end_row) { + + // Top Row + for(let i = start_col; i <= end_col; i++){ + results[start_row][i] = counter; + counter++; + } + start_row++; + + // Right Column + for(let i = start_row; i <= end_row; i++){ + results[i][end_col] = counter; + counter++; + } + end_col--; + + // Bottom Row + for(let i = end_col; i >= start_col; i--){ + results[end_row][i] = counter; + counter++; + } + end_row--; + + // Start Column + for(let i = end_row; i >= start_row; i--) { + results[i][start_col] = counter; + counter++; + } + start_col++; + } + return results; +} + +module.exports = matrix; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/test.js new file mode 100644 index 0000000..4476dda --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/matrix/test.js @@ -0,0 +1,29 @@ +const matrix = require('./index'); + +test('matrix is a function', () => { + expect(typeof matrix).toEqual('function'); +}); + +test('matrix produces a 2x2 array', () => { + const m = matrix(2); + expect(m.length).toEqual(2); + expect(m[0]).toEqual([1, 2]); + expect(m[1]).toEqual([4, 3]); +}); + +test('matrix produces a 3x3 array', () => { + const m = matrix(3); + expect(m.length).toEqual(3); + expect(m[0]).toEqual([1, 2, 3]); + expect(m[1]).toEqual([8, 9, 4]); + expect(m[2]).toEqual([7, 6, 5]); +}); + +test('matrix produces a 4x4 array', () => { + const m = matrix(4); + expect(m.length).toEqual(4); + expect(m[0]).toEqual([1, 2, 3, 4]); + expect(m[1]).toEqual([12, 13, 14, 5]); + expect(m[2]).toEqual([11, 16, 15, 6]); + expect(m[3]).toEqual([10, 9, 8, 7]); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/index.js new file mode 100644 index 0000000..0db5089 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/index.js @@ -0,0 +1,27 @@ +// --- Directions +// Given a string, return the character that is most +// commonly used in the string. +// --- Examples +// maxChar("abcccccccd") === "c" +// maxChar("apple 1231111") === "1" + +function maxChar(str) { + let max = 0; + let maxChar = ""; + let charMap = {}; + + for (let char of str){ + charMap[char] = charMap[char] + 1 || 1; + } + + for(let char in charMap){ + if(charMap[char] > max){ + max = charMap[char]; + maxChar = char; + } + } + return maxChar; + +} + +module.exports = maxChar; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/test.js new file mode 100644 index 0000000..14918ee --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/maxchar/test.js @@ -0,0 +1,14 @@ +const maxChar = require('./index'); + +test('maxChar function exists', () => { + expect(typeof maxChar).toEqual('function'); +}); + +test('Finds the most frequently used char', () => { + expect(maxChar('a')).toEqual('a'); + expect(maxChar('abcdefghijklmnaaaaa')).toEqual('a'); +}); + +test('Works with numbers in the string', () => { + expect(maxChar('ab1c1d1e1f1g1')).toEqual('1'); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/index.js new file mode 100644 index 0000000..8aa4683 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/index.js @@ -0,0 +1,26 @@ +// --- Directions +// Return the 'middle' node of a linked list. +// If the list has an even number of elements, return +// the node at the end of the first half of the list. +// *Do not* use a counter variable, *do not* retrieve +// the size of the list, and only iterate +// through the list one time. +// --- Example +// const l = new LinkedList(); +// l.insertLast('a') +// l.insertLast('b') +// l.insertLast('c') +// midpoint(l); // returns { data: 'b' } + +function midpoint(list) { + let slow = list.getFirst(); + let fast = list.getFirst(); + + while(fast.next && fast.next.next){ + slow = slow.next; + fast = fast.next.next; + } + return slow; +} + +module.exports = midpoint; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/linkedlist.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/linkedlist.js new file mode 100644 index 0000000..b7da56b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/linkedlist.js @@ -0,0 +1,178 @@ +class Node { + constructor(data, next = null) { + this.data = data; + this.next = next; + } +} + +class LinkedList { + constructor(values = []) { + this.head = null; + + for (let value of values) { + this.insertLast(value); + } + } + + clear() { + this.head = null; + } + + size() { + let counter = 0; + let node = this.head; + + while (node) { + counter++; + node = node.next; + } + + return counter; + } + + getAt(index) { + if (!this.head) { + return null; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index) { + return node; + } + node = node.next; + counter++; + } + return null; + } + + insertAt(data, index) { + if (!this.head) { + this.head = new Node(data); + return; + } + + if (index === 0) { + this.head = new Node(data, this.head); + return; + } + + let counter = 1; + let previous = this.head; + let node = this.head.next; + while (node) { + if (counter === index) { + previous.next = new Node(data, node); + return; + } + previous = node; + node = node.next; + counter++; + } + + previous.next = new Node(data, node); + } + + removeFirst() { + if (!this.head) { + return; + } + + this.head = this.head.next; + } + + removeLast() { + if (!this.head) { + return; + } + + if (!this.head.next) { + this.head = null; + return; + } + + let previous = this.head; + let node = this.head.next; + while (node.next) { + previous = node; + node = node.next; + } + previous.next = null; + } + + removeAt(index) { + if (!this.head) { + return; + } + + let counter = 0; + let node = this.head; + while (node) { + if (counter === index - 1) { + if (node.next) { + return (node.next = node.next.next); + } else { + return (node.next = null); + } + } + node = node.next; + counter++; + } + } + + getFirst() { + return this.head; + } + + insertFirst(data) { + this.head = new Node(data, this.getFirst()); + } + + getLast() { + if (!this.head) { + return null; + } + + let node = this.head; + while (node.next) { + node = node.next; + } + + return node; + } + + insertLast(data) { + const last = this.getLast(); + + if (last) { + last.next = new Node(data); + return last.next; + } else { + this.head = new Node(data); + return this.head; + } + } + + forEach(fn) { + if (!this.head) { + return null; + } + + let node = this.head; + while (node) { + fn(node); + node = node.next; + } + } + + *[Symbol.iterator]() { + let node = this.head; + while (node) { + yield node; + node = node.next; + } + } +} + +module.exports = { Node, LinkedList }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/test.js new file mode 100644 index 0000000..277597e --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/midpoint/test.js @@ -0,0 +1,46 @@ +const midpoint = require('./index'); +const L = require('./linkedlist'); +const Node = L.Node; +const LinkedList = L.LinkedList; + +test('Midpoint is a function', () => { + expect(typeof midpoint).toEqual('function'); +}); + +describe('Midpoint returns the middle node of an odd numbered list', () => { + test('when the list has 3 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + expect(midpoint(l).data).toEqual('b'); + }); + + test('when the list has 5 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + l.insertLast('e'); + expect(midpoint(l).data).toEqual('c'); + }); +}); + +describe('Midpoint returns the middle node of an even numbered list', () => { + test('when the list has 2 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + expect(midpoint(l).data).toEqual('a'); + }); + + test('when the list has 4 elements', () => { + const l = new LinkedList(); + l.insertLast('a'); + l.insertLast('b'); + l.insertLast('c'); + l.insertLast('d'); + expect(midpoint(l).data).toEqual('b'); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/package.json b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/package.json new file mode 100644 index 0000000..b978e88 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/package.json @@ -0,0 +1,14 @@ +{ + "name": "dev", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "jest": { + "testEnvironment": "node" + }, + "author": "stephen grider", + "license": "ISC" +} diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/index.js new file mode 100644 index 0000000..c8ed075 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/index.js @@ -0,0 +1,42 @@ +// --- Directions +// Given a string, return true if the string is a palindrome +// or false if it is not. Palindromes are strings that +// form the same word if it is reversed. *Do* include spaces +// and punctuation in determining if the string is a palindrome. +// --- Examples: +// palindrome("abba") === true +// palindrome("abcdefg") === false + +// function palindrome(str) { +// reversed = ""; +// for (let char of str){ +// reversed = char + reversed; +// } +// return reversed === str; +// } + +// function palindrome(str) { +// left = 0; +// right = str.length-1; + +// while (left < right) { +// if (str[left] === str[right]){ +// left += 1; +// right -= 1; +// } else { +// return false; +// } +// } +// return true; +// } + +function palindrome(str) { + return str.split('').every((char, i) => { + return char === str[str.length -i -1]; + }) +} + + + + +module.exports = palindrome; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/test.js new file mode 100644 index 0000000..abdbcb1 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/palindrome/test.js @@ -0,0 +1,33 @@ +const palindrome = require('./index'); + +test('palindrome function is defined', () => { + expect(typeof palindrome).toEqual('function'); +}); + +test('"aba" is a palindrome', () => { + expect(palindrome('aba')).toBeTruthy(); +}); + +test('" aba" is not a palindrome', () => { + expect(palindrome(' aba')).toBeFalsy(); +}); + +test('"aba " is not a palindrome', () => { + expect(palindrome('aba ')).toBeFalsy(); +}); + +test('"greetings" is not a palindrome', () => { + expect(palindrome('greetings')).toBeFalsy(); +}); + +test('"1000000001" a palindrome', () => { + expect(palindrome('1000000001')).toBeTruthy(); +}); + +test('"Fish hsif" is not a palindrome', () => { + expect(palindrome('Fish hsif')).toBeFalsy(); +}); + +test('"pennep" a palindrome', () => { + expect(palindrome('pennep')).toBeTruthy(); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/index.js new file mode 100644 index 0000000..cc55237 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/index.js @@ -0,0 +1,64 @@ +// --- Directions +// Write a function that accepts a positive number N. +// The function should console log a pyramid shape +// with N levels using the # character. Make sure the +// pyramid has spaces on both the left *and* right hand sides +// --- Examples +// pyramid(1) +// '#' +// pyramid(2) +// ' # ' +// '###' +// pyramid(3) +// ' # ' +// ' ### ' +// '#####' + +// function pyramid(n) { +// const midpoint = Math.floor((2 * n - 1) / 2); + +// for (let row = 0; row < n; row++) { +// let level = ''; + +// for (let column = 0; column < 2 * n - 1; column++) { + +// const condition = ((midpoint - row <= level.length) && (midpoint + row >= level.length)); +// condition ? level += "#" : level += " "; + +// // if((midpoint - row <= column) && (midpoint + row >= column)) { +// // level += '#'; +// // } else { +// // level += ' '; +// // } +// } +// console.log(level); +// } +// } + +function pyramid(n, row =0, level = '') { + if(row === n) { + return; + } + if(level.length === 2 * n - 1) { + console.log(level); + return pyramid(n, row + 1); + } + + const midpoint = Math.floor((2 * n - 1) / 2); + let add; + + const condition = ((midpoint - row <= level.length) && (midpoint + row >= level.length)); + condition ? add = "#" : add = " "; + + // if((midpoint - row <= level.length) && (midpoint + row >= level.length)) { + // add = '#'; + // } else { + // add = ' '; + // } + + pyramid(n, row, level + add); +} + + + +module.exports = pyramid; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/test.js new file mode 100644 index 0000000..8ffc318 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/pyramid/test.js @@ -0,0 +1,37 @@ +const pyramid = require('./index'); + +beforeEach(() => { + jest.spyOn(console, 'log'); +}); + +afterEach(() => { + console.log.mockRestore(); +}); + +test('pyramid is a function', () => { + expect(typeof pyramid).toEqual('function'); +}); + +test('prints a pryamid for n = 2', () => { + pyramid(2); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual('###'); + expect(console.log.mock.calls.length).toEqual(2); +}); + +test('prints a pryamid for n = 3', () => { + pyramid(3); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual(' ### '); + expect(console.log.mock.calls[2][0]).toEqual('#####'); + expect(console.log.mock.calls.length).toEqual(3); +}); + +test('prints a pryamid for n = 4', () => { + pyramid(4); + expect(console.log.mock.calls[0][0]).toEqual(' # '); + expect(console.log.mock.calls[1][0]).toEqual(' ### '); + expect(console.log.mock.calls[2][0]).toEqual(' ##### '); + expect(console.log.mock.calls[3][0]).toEqual('#######'); + expect(console.log.mock.calls.length).toEqual(4); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/index.js new file mode 100644 index 0000000..c575ca1 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/index.js @@ -0,0 +1,58 @@ +// --- Directions +// Implement a Queue datastructure using two stacks. +// *Do not* create an array inside of the 'Queue' class. +// Queue should implement the methods 'add', 'remove', and 'peek'. +// For a reminder on what each method does, look back +// at the Queue exercise. +// --- Examples +// const q = new Queue(); +// q.add(1); +// q.add(2); +// q.peek(); // returns 1 +// q.remove(); // returns 1 +// q.remove(); // returns 2 + +const Stack = require('./stack'); + +class Queue { + constructor() { + this.first = new Stack(); + this.second = new Stack(); + } + + add(record) { + this.first.push(record); + } + + remove() { + while(this.first.peek()){ + // let record = this.first.pop(); + this.second.push(this.first.pop()); + + } + + const record = this.second.pop(); + + while(this.second.peek()) { + this.first.push(this.second.pop()); + } + + return record; + } + + peek() { + while(this.first.peek()) { + this.second.push(this.first.pop()); + } + + const record = this.second.peek(); + + while(this.second.peek()){ + this.first.push(this.second.pop()); + } + + return record; + } +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/stack.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/stack.js new file mode 100644 index 0000000..2032acb --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/stack.js @@ -0,0 +1,19 @@ +class Stack { + constructor() { + this.data = []; + } + + push(record) { + this.data.push(record); + } + + pop() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Stack; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/test.js new file mode 100644 index 0000000..3fc84c7 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/qfroms/test.js @@ -0,0 +1,41 @@ +const Queue = require('./index'); + +test('Queue is a class', () => { + expect(typeof Queue.prototype.constructor).toEqual('function'); +}); + +test('can add elements to a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + }).not.toThrow(); +}); + +test('can remove elements from a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + q.remove(); + }).not.toThrow(); +}); + +test('Order of elements is maintained', () => { + const q = new Queue(); + q.add(1); + q.add(2); + q.add(3); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); + expect(q.remove()).toEqual(3); + expect(q.remove()).toEqual(undefined); +}); + +test('peek returns, but does not remove, the first value', () => { + const q = new Queue(); + q.add(1); + q.add(2); + expect(q.peek()).toEqual(1); + expect(q.peek()).toEqual(1); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/index.js new file mode 100644 index 0000000..ca98ee9 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/index.js @@ -0,0 +1,30 @@ +// --- Description +// Create a queue data structure. The queue +// should be a class with methods 'add' and 'remove'. +// Adding to the queue should store an element until +// it is removed +// --- Examples +// const q = new Queue(); +// q.add(1); +// q.remove(); // returns 1; + +class Queue { + + constructor() { + this.data = []; + } + + add(record) { + this.data.unshift(record); + } + + remove() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/test.js new file mode 100644 index 0000000..867bd42 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/queue/test.js @@ -0,0 +1,31 @@ +const Queue = require('./index'); + +test('Queue is a class', () => { + expect(typeof Queue.prototype.constructor).toEqual('function'); +}); + +test('can add elements to a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + }).not.toThrow(); +}); + +test('can remove elements from a queue', () => { + const q = new Queue(); + expect(() => { + q.add(1); + q.remove(); + }).not.toThrow(); +}); + +test('Order of elements is maintained', () => { + const q = new Queue(); + q.add(1); + q.add(2); + q.add(3); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); + expect(q.remove()).toEqual(3); + expect(q.remove()).toEqual(undefined); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/index.js new file mode 100644 index 0000000..822e9d3 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/index.js @@ -0,0 +1,17 @@ +// --- Directions +// Given an integer, return an integer that is the reverse +// ordering of numbers. +// --- Examples +// reverseInt(15) === 51 +// reverseInt(981) === 189 +// reverseInt(500) === 5 +// reverseInt(-15) === -51 +// reverseInt(-90) === -9 + +function reverseInt(n) { + const reversed = n.toString().split('').reverse().join(''); + + return Math.sign(n) * parseInt(reversed); +} + +module.exports = reverseInt; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/test.js new file mode 100644 index 0000000..e5092e2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reverseint/test.js @@ -0,0 +1,23 @@ +const reverseInt = require('./index'); + +test('ReverseInt function exists', () => { + expect(reverseInt).toBeDefined(); +}); + +test('ReverseInt handles 0 as an input', () => { + expect(reverseInt(0)).toEqual(0); +}); + +test('ReverseInt flips a positive number', () => { + expect(reverseInt(5)).toEqual(5); + expect(reverseInt(15)).toEqual(51); + expect(reverseInt(90)).toEqual(9); + expect(reverseInt(2359)).toEqual(9532); +}); + +test('ReverseInt flips a negative number', () => { + expect(reverseInt(-5)).toEqual(-5); + expect(reverseInt(-15)).toEqual(-51); + expect(reverseInt(-90)).toEqual(-9); + expect(reverseInt(-2359)).toEqual(-9532); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/index.js new file mode 100644 index 0000000..bc4cc56 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/index.js @@ -0,0 +1,68 @@ +// --- Directions +// Given a string, return a new string with the reversed +// order of characters +// --- Examples +// reverse('apple') === 'leppa' +// reverse('hello') === 'olleh' +// reverse('Greetings!') === '!sgniteerG' + +// function reverse(str) { +// // recursive soltuion +// if (str.length <= 1) {return str}; +// return reverse(str.slice(1)) +str[0]; +// } + + +// function reverse(str) { +// // reverse loop through string +// res = "" +// for (let i = str.length-1; i >= 0; i--){ +// res += str[i]; +// } +// return res; +// } + +// function reverse(str) { +// // split reverse join solution + +// return str.split("").reverse().join(""); +// } + + +// function reverse(str){ +// let reversed = ''; + +// for (let character of str) { +// reversed = character + reversed; +// } +// return reversed; +// } + + +function reverse(str) { + return str.split('').reduce((reversed, character) => { + return character + reversed; + }, "") +} + + + + + + + + + + + + + + + + + + + + + +module.exports = reverse; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/test.js new file mode 100644 index 0000000..8d264c0 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/reversestring/test.js @@ -0,0 +1,13 @@ +const reverse = require('./index'); + +test('Reverse function exists', () => { + expect(reverse).toBeDefined(); +}); + +test('Reverse reverses a string', () => { + expect(reverse('abcd')).toEqual('dcba'); +}); + +test('Reverse reverses a string', () => { + expect(reverse(' abcd')).toEqual('dcba '); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/index.js new file mode 100644 index 0000000..efd32e0 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/index.js @@ -0,0 +1,68 @@ +// --- Directions +// Implement bubbleSort, selectionSort, and mergeSort + +function bubbleSort(arr) { + + for (let i = 0; i < arr.length; i++) { + for(let j =0; j < arr.length - i - 1; j++){ + + if(arr[j] > arr[j+1]){ + const temp = arr[j+1]; + arr[j + 1] = arr[j]; + arr[j] = temp; + } + } + } + return arr; +} + +function selectionSort(arr) { + + for (let i = 0; i < arr.length; i++){ + let indexOfMin = i; + + for(let j = i + 1; j < arr.length; j++){ + if(arr[j] < arr[indexOfMin]){ + indexOfMin = j; + } + } + + if(indexOfMin !== i) { + let temp = arr[indexOfMin]; + arr[indexOfMin] = arr[i]; + arr[i] = temp; + } + } + return arr; +} + +function mergeSort(arr) { + if(arr.length === 1){ + return arr; + } + + const center = Math.floor(arr.length / 2); + const left = arr.slice(0, center); + const right = arr.slice(center); + + return merge(mergeSort(left), mergeSort(right)); + + + +} + +function merge(left, right) { + const results = []; + + while(left.length && right.length) { + if(left[0] < right[0]){ + results.push(left.shift()); + }else { + results.push(right.shift()); + } + } + + return [...results, ...left, ...right]; +} + +module.exports = { bubbleSort, selectionSort, mergeSort, merge }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/test.js new file mode 100644 index 0000000..0ff475b --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/sorting/test.js @@ -0,0 +1,38 @@ +const S = require('./index'); +const bubbleSort = S.bubbleSort; +const selectionSort = S.selectionSort; +const mergeSort = S.mergeSort; +const merge = S.merge; + +function getArray() { + return [100, -40, 500, -124, 0, 21, 7]; +} + +function getSortedArray() { + return [-124, -40, 0, 7, 21, 100, 500]; +} + +describe('Bubble sort', () => { + test('sorts an array', () => { + expect(bubbleSort(getArray())).toEqual(getSortedArray()); + }); +}); + +describe('Selection sort', () => { + test('sorts an array', () => { + expect(selectionSort(getArray())).toEqual(getSortedArray()); + }); +}); + +describe('Merge sort', () => { + test('merge function can join together two sorted arrays', () => { + const left = [1, 10]; + const right = [2, 8, 12]; + + expect(merge(left, right)).toEqual([1,2,8,10,12]); + }); + + test('sorts an array', () => { + expect(mergeSort(getArray())).toEqual(getSortedArray()); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/index.js new file mode 100644 index 0000000..efc8fa5 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/index.js @@ -0,0 +1,32 @@ +// --- Directions +// Create a stack data structure. The stack +// should be a class with methods 'push', 'pop', and +// 'peek'. Adding an element to the stack should +// store it until it is removed. +// --- Examples +// const s = new Stack(); +// s.push(1); +// s.push(2); +// s.pop(); // returns 2 +// s.pop(); // returns 1 + +class Stack { + + constructor() { + this.data = []; + } + + push(record) { + this.data.push(record); + } + + pop() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } +} + +module.exports = Stack; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/test.js new file mode 100644 index 0000000..457e5a2 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/stack/test.js @@ -0,0 +1,36 @@ +const Stack = require('./index'); + +test('Stack is a class', () => { + expect(typeof Stack.prototype.constructor).toEqual('function'); +}); + +test('stack can add and remove items', () => { + const s = new Stack(); + s.push(1); + expect(s.pop()).toEqual(1); + s.push(2); + expect(s.pop()).toEqual(2); +}); + +test('stack can follows first in, last out', () => { + const s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + expect(s.pop()).toEqual(3); + expect(s.pop()).toEqual(2); + expect(s.pop()).toEqual(1); +}); + +test('peek returns the first element but doesnt pop it', () => { + const s = new Stack(); + s.push(1); + s.push(2); + s.push(3); + expect(s.peek()).toEqual(3); + expect(s.pop()).toEqual(3); + expect(s.peek()).toEqual(2); + expect(s.pop()).toEqual(2); + expect(s.peek()).toEqual(1); + expect(s.pop()).toEqual(1); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/index.js new file mode 100644 index 0000000..7e9e9ed --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/index.js @@ -0,0 +1,52 @@ +// --- Directions +// Write a function that accepts a positive number N. +// The function should console log a step shape +// with N levels using the # character. Make sure the +// step has spaces on the right hand side! +// --- Examples +// steps(2) +// '# ' +// '##' +// steps(3) +// '# ' +// '## ' +// '###' +// steps(4) +// '# ' +// '## ' +// '### ' +// '####' + +// function steps(n) { +// for(let row = 0; row < n; row++) { +// let stair = ""; + +// for(let column = 0; column < n; column++){ +// if(column <= row) { +// stair += '#'; +// } else { +// stair += ' '; +// } +// } +// console.log(stair); +// } +// } + +function steps(n, row=0, stair = '') { + if (n === row) { + return; + } + + if(n === stair.length) { + console.log(stair); + return steps(n, row + 1); + } + + const add = stair.length <= row ? '#' : ' '; + steps(n, row, stair + add); +} + + + + +module.exports = steps; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/test.js new file mode 100644 index 0000000..007af11 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/steps/test.js @@ -0,0 +1,34 @@ +const steps = require('./index'); + +beforeEach(() => { + jest.spyOn(console, 'log'); +}); + +afterEach(() => { + console.log.mockRestore(); +}); + +test('steps is a function', () => { + expect(typeof steps).toEqual('function'); +}); + +test('steps called with n = 1', () => { + steps(1); + expect(console.log.mock.calls[0][0]).toEqual('#'); + expect(console.log.mock.calls.length).toEqual(1); +}); + +test('steps called with n = 2', () => { + steps(2); + expect(console.log.mock.calls[0][0]).toEqual('# '); + expect(console.log.mock.calls[1][0]).toEqual('##'); + expect(console.log.mock.calls.length).toEqual(2); +}); + +test('steps called with n = 3', () => { + steps(3); + expect(console.log.mock.calls[0][0]).toEqual('# '); + expect(console.log.mock.calls[1][0]).toEqual('## '); + expect(console.log.mock.calls[2][0]).toEqual('###'); + expect(console.log.mock.calls.length).toEqual(3); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/index.js new file mode 100644 index 0000000..f69a05d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/index.js @@ -0,0 +1,61 @@ +// --- Directions +// 1) Create a node class. The constructor +// should accept an argument that gets assigned +// to the data property and initialize an +// empty array for storing children. The node +// class should have methods 'add' and 'remove'. +// 2) Create a tree class. The tree constructor +// should initialize a 'root' property to null. +// 3) Implement 'traverseBF' and 'traverseDF' +// on the tree class. Each method should accept a +// function that gets called with each element in the tree + +class Node { + constructor(data){ + this.data = data; + this.children = []; + } + + add(data){ + // const node = new Node(data); + this.children.push(new Node(data)); + } + + remove(data){ + this.children = this.children.filter(node => { + return node.data != data; + }); + } + +} + +class Tree { + constructor(){ + this.root = null; + } + + traverseBF(fn){ + const arr = [this.root]; + while(arr.length){ + const node = arr.shift(); + + arr.push(...node.children); + fn(node); + // for(let child of node.children){ + // arr.push(child); + // } + } + } + + traverseDF(fn){ + const arr = [this.root]; + while(arr.length){ + const node = arr.shift(); + + arr.unshift(...node.children); + fn(node); + } + } +} + +module.exports = { Tree, Node }; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/test.js new file mode 100644 index 0000000..69dab5d --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/tree/test.js @@ -0,0 +1,67 @@ +const T = require('./index'); +const Node = T.Node; +const Tree = T.Tree; + +describe('Node', () => { + test('Node is a constructor', () => { + expect(typeof Node.prototype.constructor).toEqual('function'); + }); + + test('Node has a data and children properties', () => { + const n = new Node('a'); + expect(n.data).toEqual('a'); + expect(n.children.length).toEqual(0); + }); + + test('Node can add children', () => { + const n = new Node('a'); + n.add('b'); + expect(n.children.length).toEqual(1); + expect(n.children[0].children).toEqual([]); + }); + + test('Node can remove children', () => { + const n = new Node('a'); + n.add('b'); + expect(n.children.length).toEqual(1); + n.remove('b'); + expect(n.children.length).toEqual(0); + }); +}); + +describe('Tree', () => { + test('starts empty', () => { + const t = new Tree(); + expect(t.root).toEqual(null); + }); + + test('Can traverse bf', () => { + const letters = []; + const t = new Tree(); + t.root = new Node('a'); + t.root.add('b'); + t.root.add('c'); + t.root.children[0].add('d'); + + t.traverseBF(node => { + letters.push(node.data); + }); + + expect(letters).toEqual(['a', 'b', 'c', 'd']); + }); + + test('Can traverse DF', () => { + const letters = []; + const t = new Tree(); + t.root = new Node('a'); + t.root.add('b'); + t.root.add('d'); + t.root.children[0].add('c'); + + t.traverseDF(node => { + letters.push(node.data); + }); + + expect(letters).toEqual(['a', 'b', 'c', 'd']); + }); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/index.js new file mode 100644 index 0000000..e9c3fc9 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/index.js @@ -0,0 +1,29 @@ +// --- Directions +// Given a node, validate the binary search tree, +// ensuring that every node's left hand child is +// less than the parent node's value, and that +// every node's right hand child is greater than +// the parent + +function validate(node, min = null, max = null) { + + if(max !== null && node.data > max){ + return false; + } + + if(min !== null && node.data < min){ + return false; + } + + if(node.left && !validate(node.left, min, node.data)){ + return false; + } + + if(node.right && !validate(node.right, node.data, max)){ + return false; + } + + return true; +} + +module.exports = validate; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/node.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/node.js new file mode 100644 index 0000000..d19e208 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/node.js @@ -0,0 +1,21 @@ +class Node { + constructor(data) { + this.data = data; + this.left = null; + this.right = null; + } + + insert(data) { + if (data < this.data && this.left) { + this.left.insert(data); + } else if (data < this.data) { + this.left = new Node(data); + } else if (data > this.data && this.right) { + this.right.insert(data); + } else if (data > this.data) { + this.right = new Node(data); + } + } +} + +module.exports = Node; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/test.js new file mode 100644 index 0000000..6ea4dc3 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/validate/test.js @@ -0,0 +1,23 @@ +const Node = require('./node'); +const validate = require('./index'); + +test('Validate recognizes a valid BST', () => { + const n = new Node(10); + n.insert(5); + n.insert(15); + n.insert(0); + n.insert(20); + + expect(validate(n)).toEqual(true); +}); + +test('Validate recognizes an invalid BST', () => { + const n = new Node(10); + n.insert(5); + n.insert(15); + n.insert(0); + n.insert(20); + n.left.left.right = new Node(999); + + expect(validate(n)).toEqual(false); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/index.js new file mode 100644 index 0000000..a274eac --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/index.js @@ -0,0 +1,29 @@ +// --- Directions +// Write a function that returns the number of vowels +// used in a string. Vowels are the characters 'a', 'e' +// 'i', 'o', and 'u'. +// --- Examples +// vowels('Hi There!') --> 3 +// vowels('Why do you ask?') --> 4 +// vowels('Why?') --> 0 + +// function vowels(str) { +// let count = 0; + +// const checker = ['a', 'e', 'i', 'o', 'u'] + +// for (let char of str.toLowerCase()) { +// if(checker.includes(char)){ +// count++; +// } +// } +// return count; +// } + +function vowels(str) { + const matches = str.match(/[aeiou]/gi); + return matches ? matches.length : 0; +} + + +module.exports = vowels; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/test.js new file mode 100644 index 0000000..6283592 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/vowels/test.js @@ -0,0 +1,21 @@ +const vowels = require('./index'); + +test('Vowels is a function', () => { + expect(typeof vowels).toEqual('function'); +}); + +test('returns the number of vowels used', () => { + expect(vowels('aeiou')).toEqual(5); +}); + +test('returns the number of vowels used when they are capitalized', () => { + expect(vowels('AEIOU')).toEqual(5); +}); + +test('returns the number of vowels used', () => { + expect(vowels('abcdefghijklmnopqrstuvwxyz')).toEqual(5); +}); + +test('returns the number of vowels used', () => { + expect(vowels('bcdfghjkl')).toEqual(0); +}); diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/index.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/index.js new file mode 100644 index 0000000..480c108 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/index.js @@ -0,0 +1,45 @@ +// --- Directions +// 1) Complete the task in weave/queue.js +// 2) Implement the 'weave' function. Weave +// receives two queues as arguments and combines the +// contents of each into a new, third queue. +// The third queue should contain the *alterating* content +// of the two queues. The function should handle +// queues of different lengths without inserting +// 'undefined' into the new one. +// *Do not* access the array inside of any queue, only +// use the 'add', 'remove', and 'peek' functions. +// --- Example +// const queueOne = new Queue(); +// queueOne.add(1); +// queueOne.add(2); +// const queueTwo = new Queue(); +// queueTwo.add('Hi'); +// queueTwo.add('There'); +// const q = weave(queueOne, queueTwo); +// q.remove() // 1 +// q.remove() // 'Hi' +// q.remove() // 2 +// q.remove() // 'There' + +const Queue = require('./queue'); + +function weave(sourceOne, sourceTwo) { + + const q = new Queue(); + + while(sourceOne.peek() || sourceTwo.peek()) { + + if(sourceOne.peek()) { + q.add(sourceOne.remove()); + } + if(sourceTwo.peek()) { + q.add(sourceTwo.remove()); + } + } + + return q; + +} + +module.exports = weave; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/queue.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/queue.js new file mode 100644 index 0000000..fe93359 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/queue.js @@ -0,0 +1,26 @@ +// --- Directions +// Implement a 'peek' method in this Queue class. +// Peek should return the last element (the next +// one to be returned) from the queue *without* +// removing it. + +class Queue { + constructor() { + this.data = []; + } + + add(record) { + this.data.unshift(record); + } + + remove() { + return this.data.pop(); + } + + peek() { + return this.data[this.data.length - 1]; + } + +} + +module.exports = Queue; diff --git a/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/test.js b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/test.js new file mode 100644 index 0000000..f173360 --- /dev/null +++ b/Grider-Stephen-AlgoCasts-JS-Practice/exercises/weave/test.js @@ -0,0 +1,45 @@ +const weave = require('./index'); +const Queue = require('./queue'); + +test('queues have a peek function', () => { + const q = new Queue(); + expect(typeof q.peek).toEqual('function'); +}); + +test('peek returns, but does not remove, the first value', () => { + const q = new Queue(); + q.add(1); + q.add(2); + expect(q.peek()).toEqual(1); + expect(q.peek()).toEqual(1); + expect(q.remove()).toEqual(1); + expect(q.remove()).toEqual(2); +}); + +test('weave is a function', () => { + expect(typeof weave).toEqual('function'); +}); + +test('weave can combine two queues', () => { + const one = new Queue(); + one.add(1); + one.add(2); + one.add(3); + one.add(4); + const two = new Queue(); + two.add('one'); + two.add('two'); + two.add('three'); + two.add('four'); + + const result = weave(one, two); + expect(result.remove()).toEqual(1); + expect(result.remove()).toEqual('one'); + expect(result.remove()).toEqual(2); + expect(result.remove()).toEqual('two'); + expect(result.remove()).toEqual(3); + expect(result.remove()).toEqual('three'); + expect(result.remove()).toEqual(4); + expect(result.remove()).toEqual('four'); + expect(result.remove()).toBeUndefined(); +}); diff --git a/Nguyen-Kevin-JS-Leet-Practice/longestSubstring.js b/Nguyen-Kevin-JS-Leet-Practice/longestSubstring.js new file mode 100644 index 0000000..25e1840 --- /dev/null +++ b/Nguyen-Kevin-JS-Leet-Practice/longestSubstring.js @@ -0,0 +1,17 @@ +function lengthOfLongestSubstring(s) { + let windowCharsMap = {}; + let windowStart = 0; + let maxLength = 0; + + for (let i =0; i < s.length; i++) { + const endChar = s[i]; + + if(windowCharsMap[endChar] >= windowStart) { + windowStart = windowCharsMap[endChar] + 1; + } + + windowCharsMap[endChar] = i; + maxLength = Math.max(maxLength, i - windowStart + 1); + } + return maxLength; +} \ No newline at end of file diff --git a/Nguyen-Kevin-JS-Leet-Practice/palindrome.js b/Nguyen-Kevin-JS-Leet-Practice/palindrome.js new file mode 100644 index 0000000..a0f1fb3 --- /dev/null +++ b/Nguyen-Kevin-JS-Leet-Practice/palindrome.js @@ -0,0 +1,17 @@ + +function isParlindrome(s){ + s =s.toLowerCase().replace(/[^\w]/g, ""); + + let left = 0; + let right = s.length -1; + + while(left < right) { + if (s[left] !== s[right]){ + return false; + } + left++; + right--; + } + return true; +} + diff --git a/Traub-Eric-JS-Practice/6_hoisting.js b/Traub-Eric-JS-Practice/6_hoisting.js index e69de29..465f1b0 100644 --- a/Traub-Eric-JS-Practice/6_hoisting.js +++ b/Traub-Eric-JS-Practice/6_hoisting.js @@ -0,0 +1,101 @@ +/* ex 1 +first console log fails +due to variable hoisting +before variable assignment +*/ + +console.log(color); +var color = "red"; +console.log(color); + + + +//ex 2 +var color; +console.log(color); +color = "orange"; +console.log(color); + + + +// ex 3 +/* +function expression vs +function declaration +*/ + +console.log(getProduct(2, 3)); +var getProduct = function(num1, num2) { + return num1 * num2; +}; +console.log(getProduct(2, 3)); + + + +// ex 4 + +console.log(getProduct(2, 3)); +function getProduct(num1, num2) { + return num1 * num2; +} + + + +// ex 5 +/* +hoisting of varibles only +occur within encompassing function +*/ + +var globalVar = 'global'; +(function() { + var name = 'Jen'; + var getAge = function() { + return '30'; + }; + function getState() { + return 'Delaware'; + } +})(); + + +// ex 6 + +function getTotal() { + console.log(multiplier); + console.log(total); + + let total = 0; + for(var i = 0; i < 10; i++) { + let valueToAdd = i; + var multiplier = 2; + total += valueToAdd * multiplier; + } + return total; + } + getTotal(); + + + + // ex 7 + /* + keywords with let, const are not initialized + until they are declared + */ + + function getTotal() { + let total; + var multiplier; + + total = 0; + + for(var i = 0; i < 10; i++) { + let valueToAdd; + valueToAdd = i; + multiplier = 2; + total += valueToAdd * multiplier; + } + return total; + } + + getTotal(); \ No newline at end of file diff --git a/Traversy_Brad_Modern_JS/index.html b/Traversy_Brad_Modern_JS/index.html new file mode 100644 index 0000000..f15b337 --- /dev/null +++ b/Traversy_Brad_Modern_JS/index.html @@ -0,0 +1,13 @@ + + + + + + Document + + +

Objects

+ + + + \ No newline at end of file diff --git a/Traversy_Brad_Modern_JS/script.js b/Traversy_Brad_Modern_JS/script.js new file mode 100644 index 0000000..5b0e602 --- /dev/null +++ b/Traversy_Brad_Modern_JS/script.js @@ -0,0 +1,618 @@ +class Wallet { + #balance = 0; + #transactions = []; + + + constructor() { + this._balance = 0; + this._transactions = []; + } + + deposit(amount) { + this.#processDeposit(amount); + this.#balance += amount; + } + + withdraw(amount) { + if(amount >= this.#balance){ + console.log('Not enough funds'); + return; + } + this.#processWithdraw(amount); + this.#balance -= amount; + } + + #processDeposit(amount) { + console.log(`Depositng ${amount}`); + + this._transactions.push({ + type: 'deposit', + amount + }) + } + + #processWithdraw(amount) { + console.log(`Withdrawing ${amount}`); + + this._transactions.push({ + type: 'withdraw', + amount + }) + } + + get balance() { + return this.#balance; + } + + get transactions() { + return this.#transactions; + } +} + +const wallet = new Wallet(); +wallet.deposit(300); +wallet.withdraw(50); +// console.log(wallet._balance); +// console.log(wallet.balance); +// console.log(wallet.transactions); + +// console.log(wallet.#balance); +console.log(wallet.transactions); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// // Constructor function +// function Person (firstName, lastName){ +// this._firstName = firstName; +// this._lastName = lastName; + +// Object.defineProperty(this, 'firstName', { +// get: function () { +// return this.captializeFirst(this._firstName); +// }, +// set: function (value) { +// this._firstName = value; +// } +// }); + +// Object.defineProperty(this, 'lastName', { +// get: function () { +// return this.captializeFirst(this._lastName); +// }, +// set: function (value) { +// this._lasstName = value; +// } +// }); + +// Object.defineProperty(this, 'fullName', { +// get: function () { +// return this.firstName + " " + this.lastName; +// }, +// }); + +// } + +// Person.prototype.captializeFirst = function(value) { +// return value.charAt(0).toUpperCase() + value.slice(1); +// }; + +// //Object literal +// const PersonObj = { +// _firstName: 'jane', +// _lastName: 'doe', + +// get firstName() { +// return Person.prototype.captializeFirst(this._firstName) +// }, + +// set firstName(value) { +// this._firstName = value; +// }, + +// get lastName() { +// return Person.prototype.captializeFirst(this._lastName); +// }, + +// set lastName(value) { +// this._lastName = value; +// }, + +// get fullName() { +// return this._firstName + " " + this.lastName; +// } +// } + +// const person1 = new Person('john', 'doe'); +// console.log(person1.firstName); +// console.log(person1.lastName); +// console.log(person1.fullName); + +// const person2 = new Person('jane', 'dough'); +// console.log(person2.firstName); +// console.log(person2.lastName); +// console.log(person2.fullName); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// class Person { +// constructor (firstName, lastName) { +// this._firstName = firstName; +// this._lastName = lastName; +// } + +// get firstName() { +// // return this._firstName.charAt(0).toUpperCase() + this._firstName.slice(1); +// return this.captializeFirst(this._firstName); +// } + +// set firstName(value) { +// this._firstName = value.charAt(0).toUpperCase() + value.slice(1); +// } + +// get lastName() { +// // return this._firstName.charAt(0).toUpperCase() + this._firstName.slice(1); +// return this.captializeFirst(this._lastName); +// } + +// set lastName(value) { +// this._lastName = value.charAt(0).toUpperCase() + value.slice(1); +// } + +// captializeFirst(value) { +// return value.charAt(0).toUpperCase() + value.slice(1); +// } + +// get fullName() { +// return `${this.firstName} ${this._lastName}`; +// } +// } + + +// const person1 = new Person('john', 'doe'); +// console.log(person1.firstName); +// console.log(person1.lastName); + + +// person1.firstName = 'joseph'; +// person1.lastName = 'smith'; +// console.log(person1); +// console.log(person1.fullName); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// class App { +// constructor() { +// this.serverName = 'localhost'; + +// document.querySelector('button').addEventListener('Click', this.getServerName.bind(this)); +// } + +// getServerName() { +// console.log(this.serverName); +// } +// } + +// const app = new App(); +// // app.getServerName(); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// class Rectangle { +// constructor(name, height, width) { +// this.name = name; +// this.height = height; +// this.width = width; +// } + +// area() { +// return this.height * this.width; +// } + +// static getClass() { +// return 'Rectangle'; +// } +// } + + +// const rect = new Rectangle('Rect', 10, 10); +// console.log(rect.area()); +// console.log(Rectangle.getClass()); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// // Parent class +// class Shape { +// constructor(name) { +// this.name = name; +// } + +// logName() { +// console.log('Shape name: ', this.name); +// } +// } + +// // Sub Class +// class Rectangle extends Shape { +// constructor(name, width, height) { +// super(name); + +// this.height = height; +// this.width = width; +// } +// } + +// class Circle extends Shape { +// constructor(name, radius) { +// super(name); + +// this.readius = radius; +// } + +// logName() { +// console.log('Circle Name: ' + this.name) +// } +// } + + + + +// const rect = new Rectangle('Rect 1', 20, 20); +// console.log(rect); +// rect.logName(); + +// const cir = new Circle('Cir 1', 30); +// cir.logName(); + +// console.log(rect instanceof Rectangle); +// console.log(rect instanceof Shape); + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// function Player(name) { +// this.name = name; +// this.lvl = 1; +// this.points = 0; +// } + +// Player.prototype.gainXp = function (xp) { +// this.points += xp; + +// if(this.points >= 10) +// { this.lvl++; +// this.points -= 10; +// } +// } + +// Player.prototype.describe = function(){ +// return `${this.name} is level ${this.lvl} with ${this.points} +// experience points`; +// } + +// const player1 = new Player('Bob'); +// const player2 = new Player('Alice'); + +// player1.gainXp(4); +// player2.gainXp(7); +// player1.gainXp(5); +// player2.gainXp(1); +// player1.gainXp(7); +// player2.gainXp(9); +// player1.gainXp(5); +// player2.gainXp(2); + +// console.log(player1.describe()); +// console.log(player2.describe()); + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +// function Rectangle(name, width, height) { +// this.name = name; +// this.width = width; +// this.height = height; +// this.area = function() { +// return this.width * this.height; +// }; +// } + +// const rect = new Rectangle('React', 10, 10); +// console.log(rect); + +// Rectangle.prototype.area = function () { +// return (this.width * this.height); +// } + +// const rectanglePrototypes = { +// area: function () { +// return this.width * this.height +// }, +// perimeter: function () { +// return 2 * (this.width + this.height) +// }, +// isSquare: function () { +// return (this.height === this.width) +// } +// } + + +// function createRectangle(height, width) { +// return Object.create(rectanglePrototypes, { +// height: { +// value: height, +// }, +// width: { +// value: width, +// }, +// }); +// } + +// const rect = createRectangle(10, 20); +// console.log(rect); +// console.log(rect.area()); +// console.log(rect.isSquare()); + +// const rect2 = createRectangle(20, 20); +// console.log(rect2.area()); + + + + + + + + + + + + + + + + + + + + + + + +// const strLit = 'hello'; +// const strObj = new String('HELLO'); + +// console.log(strLit, typeof strLit); +// console.log(strObj, typeof strObj); + +// console.log(strLit.toUpperCase()); +// console.log(strLit[0]); + +// const funcLit = function(x) { +// return x * x; +// } + +// console.log(funcLit, typeof funcLit); + +// const funcObj = new Function('x', 'return x * x'); + +// console.log(funcObj(3)); + +// const obj1 = {}; +// const obj2 = new Object(); + +// console.log(obj1, typeof obj1); +// console.log(obj2, typeof obj2); +