diff --git a/Data-Structures/LinkList/__tests__/linked-list.test.js b/Data-Structures/LinkList/__tests__/linked-list.test.js new file mode 100644 index 0000000..b4cfe02 --- /dev/null +++ b/Data-Structures/LinkList/__tests__/linked-list.test.js @@ -0,0 +1,8 @@ +const LinkList = require('../linked-list.js'); + +xdescribe('Test', () => { + // How might we repeat this to check on types? + it('true', ()=>{ + expect(LinkList).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/Data-Structures/LinkList/linked-list.js b/Data-Structures/LinkList/linked-list.js new file mode 100644 index 0000000..e69de29 diff --git a/Data-Structures/LinkList/readme.md b/Data-Structures/LinkList/readme.md new file mode 100644 index 0000000..4da3d71 --- /dev/null +++ b/Data-Structures/LinkList/readme.md @@ -0,0 +1,22 @@ +# Singly Linked List + + + +## Challenge +Write tests to prove the following functionality: + +* Can successfully instantiate an empty linked list +* Can properly insert into the linked list +* The head property will properly point to the first node in the linked list +* Can properly insert multiple nodes into the linked list +* Will return true when finding a value within the linked list that exists +* Will return false when searching for a value in the linked list that does not exist +* Can properly return a collection of all the values that exist in the linked list + +## Approach & Efficiency + + + +## API + + \ No newline at end of file diff --git a/Data-Structures/Sorting/InsertionSort/README.md b/Data-Structures/Sorting/InsertionSort/README.md new file mode 100644 index 0000000..8efd12f --- /dev/null +++ b/Data-Structures/Sorting/InsertionSort/README.md @@ -0,0 +1,22 @@ +# Insertion Sort + +## Links + +- [Link to Pull Request](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/15) +- [Link to Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms) + +## Whiteboard / Drawing + + + +## Challenge + +Write a function called `insertionSort`, which takes an array of numbers and returns a sorted array after using the Insertion Sort algorithm. Do not mutate (change) the array given to you as a parameter. + +## Approach & Efficiency + +O(n) since we do not mutate the array in place and create a duplicate array that we manipulate + +## API + +`InsertionSort(array)` function that takes in an array as a parameter \ No newline at end of file diff --git a/Data-Structures/Sorting/InsertionSort/__tests__/insertion-sort.test.js b/Data-Structures/Sorting/InsertionSort/__tests__/insertion-sort.test.js new file mode 100644 index 0000000..61ae830 --- /dev/null +++ b/Data-Structures/Sorting/InsertionSort/__tests__/insertion-sort.test.js @@ -0,0 +1,54 @@ +'use strict'; +const InsertionSort = require('../insertion-sort'); + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// Sort array of length 1 +xdescribe('Insertion Sort Tests', () => { + it('Sort array of length 1', ()=>{ + let array = [ 13 ]; + let sortedArray = InsertionSort(array); + console.log(sortedArray); + expect(sortedArray).toEqual([13]); + }); + // Sort array of length 2 + it('Sort array of length 2', ()=>{ + let array = [13, 5]; + let sortedArray = InsertionSort(array); + expect(sortedArray).toEqual([5, 13]); + }); + // Sort array of length 10 + it('Sort array of length 10', ()=>{ + let array = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + let sortedArray = InsertionSort(array); + expect(sortedArray).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + }); + // Incorrect parameter error handling + xit('Incorrect parameter error handling', ()=>{ + let sortedArray = InsertionSort(); + expect(sortedArray).toBe('Incorrect parameter'); + }); + // Not an array + it('Not an array', ()=>{ + let array = 'animal'; + let sortedArray = InsertionSort(array); + expect(sortedArray).toBe('Not an array'); + }); + // Empty array + it('Empty array', ()=>{ + let array = []; + console.log(array[0]); + let sortedArray = InsertionSort(array); + expect(sortedArray).toBe('Empty array'); + }); + // Array with non-numerical values + it('Array with non-numerical values', ()=>{ + let array = ['blue']; + let sortedArray = InsertionSort(array); + expect(sortedArray).toBe('Array with non-numerical values'); + }); +}); \ No newline at end of file diff --git a/Data-Structures/Sorting/InsertionSort/insertion-sort.js b/Data-Structures/Sorting/InsertionSort/insertion-sort.js new file mode 100644 index 0000000..e974d7d --- /dev/null +++ b/Data-Structures/Sorting/InsertionSort/insertion-sort.js @@ -0,0 +1,33 @@ +'use strict'; + +function insertionSort(array) { + let answer =[...array]; + if(Array.isArray(array) != true){ + return('Not an array'); + } + if(array.length === 0){ + return('Empty array'); + } + if(typeof array[0] != 'number'){ + return('Array with non-numerical values'); + } + else{ + let i = 0; + while(i <= answer.length){ + let j =1; + while(j > 0){ + if(answer[j-1] > answer[j]){ + let temp = answer[j]; + answer[j] = answer[j-1]; + answer[j-1] = temp; + } + j = j-1; + } + i++; + } + return answer; + } + +} + +module.exports = insertionSort; \ No newline at end of file diff --git a/Data-Structures/Sorting/MergeSort/README.md b/Data-Structures/Sorting/MergeSort/README.md new file mode 100644 index 0000000..e27af6c --- /dev/null +++ b/Data-Structures/Sorting/MergeSort/README.md @@ -0,0 +1,24 @@ +## Links + +- [Link to Pull Request](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/16) +- [Link to Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms) + + +## Whiteboard / Drawing + + + +## Challenge + +Write a function called mergeSort, which takes an array of numbers and returns a sorted array after using the Merge Sort algorithm. Do not mutate (change) the array given to you as a parameter. + +## Approach & Efficiency + + Best case scenario is Big O(nlog(n)) + space is Big O(n) + +## API + +`mergeSort(arr)` takes in an unsorted array and will return a sorted array +`sort(temp, sIndx, eIndx)` +`merge(arr, sIndx, mid, eIndx)` \ No newline at end of file diff --git a/Data-Structures/Sorting/MergeSort/__tests__/merge-sort.test.js b/Data-Structures/Sorting/MergeSort/__tests__/merge-sort.test.js new file mode 100644 index 0000000..6f6e5ee --- /dev/null +++ b/Data-Structures/Sorting/MergeSort/__tests__/merge-sort.test.js @@ -0,0 +1,45 @@ +const mergeSort = require('../merge-sort'); + + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + + +// Incorrect parameter error handling +describe('Incorrect parameter error handling', () => { + // Not an array + it('Not an array', ()=>{ + let testArray = {}; + expect( mergeSort(testArray)).toBe('Not an array'); + }); + // Empty array + it('Empty array', ()=>{ + let testArray = []; + expect( mergeSort(testArray)).toBe('Empty array'); + }); + // Array with non-numerical values + it('Array with non-numerical values', ()=>{ + let testArray = ['a', 'c']; + expect( mergeSort(testArray)).toBe('Not an array of only numerical values'); + }); +}); +describe('Sorting tests', () => { + // Sort array of length 1 + it('Sort array of length 1', ()=>{ + let testOne = [42]; + expect(mergeSort(testOne)).toEqual([42]); + }); + // Sort array of length 2 + it('Sort array of length 2', ()=>{ + let testOne = [4, 2]; + expect(mergeSort(testOne)).toEqual([2, 4]); + }); + // Sort array of length 10 + it('Sort array of length 10', ()=>{ + let testOne = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + expect(mergeSort(testOne)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + }); +}); \ No newline at end of file diff --git a/Data-Structures/Sorting/MergeSort/merge-sort.js b/Data-Structures/Sorting/MergeSort/merge-sort.js new file mode 100644 index 0000000..4784d5d --- /dev/null +++ b/Data-Structures/Sorting/MergeSort/merge-sort.js @@ -0,0 +1,47 @@ +'use strict'; + +function mergeSort(arr) { + if(Array.isArray(arr) === false) { + return 'Not an array'; + } + if(!arr.every(el => typeof el === 'number')) { + return 'Not an array of only numerical values'; + } + if(!arr.length) { + return 'Empty array'; + } + if(arr.length === 1) { + return arr; + } + let temp = [...arr]; + + function sort(temp, sIndx, eIndx) { + if(sIndx >= eIndx) { + return; + } + let mid = Math.floor((sIndx + eIndx)/2); + sort(temp, sIndx, mid); + sort(temp, mid + 1, eIndx); + merge(temp, sIndx, mid, eIndx); + } + sort(temp, 0, temp.length - 1); + return temp; +} + +function merge(arr, sIndx, mid, eIndx) { + let merged = []; + let j = mid +1; + for(let i = sIndx; i <= mid; i++){ + while(arr[i] > arr[j] && j <= eIndx) { + merged.push(arr[j]); + j++; + } + + merged.push(arr[i]); + } + for(let i = 0; i < merged.length; i++) { + arr[sIndx + i] = merged[i]; + } +} + +module.exports = mergeSort; \ No newline at end of file diff --git a/Data-Structures/Sorting/quicksort/README.md b/Data-Structures/Sorting/quicksort/README.md new file mode 100644 index 0000000..f92f914 --- /dev/null +++ b/Data-Structures/Sorting/quicksort/README.md @@ -0,0 +1,23 @@ +# Quicksort + +## Links + +- [Link to Pull Request](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/17) +- [Link to Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/builds/143058429) + + +## Whiteboard / Drawing + + + +## Challenge + +Write a function called quicksort, which takes an array of numbers and returns a sorted array after using the Quicksort algorithm. Do not mutate (change) the array given to you as a parameter. + +## Approach & Efficiency + +Optimally this sorting algorithm will have a Big O(nlog(n)) However in the worst case it would have a Big O(n^2) + +## API + +`quicksort(arr, sIndx, eIndx) ` This will take in an array & sort it using the quick sort algorithm. \ No newline at end of file diff --git a/Data-Structures/Sorting/quicksort/__tests__/quicksort.test.js b/Data-Structures/Sorting/quicksort/__tests__/quicksort.test.js new file mode 100644 index 0000000..280eb66 --- /dev/null +++ b/Data-Structures/Sorting/quicksort/__tests__/quicksort.test.js @@ -0,0 +1,44 @@ +const quicksort = require('../quicksort'); +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); +// Incorrect parameter error handling +describe('Incorrect parameter error handling', () => { + // Not an array + it('Not an array', ()=>{ + let testArray = {}; + expect( quicksort(testArray)).toBe('Not an array'); + }); + // Empty array + it('Empty array', ()=>{ + let testArray = []; + expect( quicksort(testArray)).toBe('Empty array'); + }); + // Array with non-numerical values + it('Array with non-numerical values', ()=>{ + let testArray = ['a', 'c']; + expect( quicksort(testArray)).toBe('Not an array of only numerical values'); + }); +}); +describe('Sorting tests', () => { + // Sort array of length 1 + it('Sort array of length 1', ()=>{ + let testOne = [42]; + let eIndx = testOne.length -1; + expect(quicksort(testOne, 0, eIndx)).toEqual([42]); + }); + // Sort array of length 2 + it('Sort array of length 2', ()=>{ + let testTwo = [4, 2]; + let eIndxTwo = testTwo.length - 1; + expect(quicksort(testTwo, 0, eIndxTwo)).toEqual([2, 4]); + }); + // Sort array of length 10 + it('Sort array of length 10', ()=>{ + let testTen = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1]; + let eIndxTen = testTen.length - 1; + expect(quicksort(testTen, 0, eIndxTen)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + }); +}); \ No newline at end of file diff --git a/Data-Structures/Sorting/quicksort/quicksort.js b/Data-Structures/Sorting/quicksort/quicksort.js new file mode 100644 index 0000000..5d55dd0 --- /dev/null +++ b/Data-Structures/Sorting/quicksort/quicksort.js @@ -0,0 +1,53 @@ +'use strict'; +function quicksort(arr, sIndx, eIndx) { + let pivot; + if(Array.isArray(arr) === false) { + return 'Not an array'; + } + if(!arr.every(el => typeof el === 'number')) { + return 'Not an array of only numerical values'; + } + if(!arr.length) { + return 'Empty array'; + } + if(arr.length === 1) { + return arr; + } + if(arr.length > 1){ + pivot = partition(arr, sIndx, eIndx); + if (sIndx < pivot - 1){ + quicksort(arr, sIndx, pivot - 1); + } + if(pivot < eIndx){ + quicksort(arr, pivot + 1, eIndx); + } + } + return arr; +} +function swap(arr, left, right){ + let temp = arr[left]; + arr[left] = arr[right]; + arr[right] = temp; +} +function partition(arr, left, right){ + let pivot = arr[Math.floor((left + right) / 2)]; + let i = left; + let j = right; + while (i <= j) { + while (arr[i] < pivot) { + i++; + } + while (arr[j] > pivot) { + j--; + } + if (i <= j) { + swap(arr, i, j); + i++; + j--; + } + } + return i; +} + + +module.exports = quicksort; \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/__tests__/linked-list.test.js b/Data-Structures/ll-Insertions/__tests__/linked-list.test.js new file mode 100644 index 0000000..0146148 --- /dev/null +++ b/Data-Structures/ll-Insertions/__tests__/linked-list.test.js @@ -0,0 +1,150 @@ +const LinkedList = require('../linked-list.js'); + +xdescribe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +xdescribe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +xdescribe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +xdescribe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +xdescribe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +xdescribe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +xdescribe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +xdescribe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +xdescribe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/linked-list.js b/Data-Structures/ll-Insertions/linked-list.js new file mode 100644 index 0000000..2ad5141 --- /dev/null +++ b/Data-Structures/ll-Insertions/linked-list.js @@ -0,0 +1,89 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/node.js b/Data-Structures/ll-Insertions/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-Insertions/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-Insertions/readme.md b/Data-Structures/ll-Insertions/readme.md new file mode 100644 index 0000000..a2c5d28 --- /dev/null +++ b/Data-Structures/ll-Insertions/readme.md @@ -0,0 +1,43 @@ +# Singly Linked List + +More complex functions for singly linked lists + +## Challenge +* Have a class named Node. This class should contain: + A variable to hold data (i.e. this.data) + A variable to hold the next Node object (i.e. this.next) +* Have a class named LinkedList. This class should contain: + A variable named head which holds the Node object that starts the list + A constructor that instantiates head as an empty linked list + A function called insert which takes in a value. This function will then create a new Node object, sets the object’s data property equal to the value. The function then appends this new Node object to the beginning of the linked list (i.e. it sets a new head) + A function called includes which takes in a value and returns a boolean if that value exists in the linked list + A function called toString whcih takes in no arguments and returns a string representing all the values in the linked list + A function called append which adds a Node to the end of the list + A function called insertBefore which adds a Node before a certain Node in the list + A function called insertAfter which adds a Node after a certain Node in the list +Implement good error checking throughout your code. Create custom errors that describe what went wrong. +Structure and Testing +Any functions you write should be clean, reusable and independent component parts to the whole program. + +#### Write tests to prove the following functionality: + +* Can successfully add a node to the end of the linked list +* Can successfully add multiple nodes to the end of a linked list +* Can successfully insert a node before a node located in the middle of a linked list +* Can successfully insert a node before the first node of a linked list +* Can successfully insert after a node in the middle of the linked list +* Can successfully insert a node after the last node of the linked list + +## Approach & Efficiency + +O(n) +We never go deeper than one interation of the list so Big O(n) is still applicable + +## API + +insert(data) - Creates a new Node Object. Appends the new Node object to the beginning of the linked list +includes(searchValue) - Takes in a value as a paramenter and returns a boolean if the value exists in the linked list +toString() - Returns a string with all the values in the linked list +append(data) - Adds a node to the end of the list +insertBefore(data, before) - Adds a Node before a certain Node in the list +insertAfter(data, after) - Adds a Node after a certain Node in the list \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js b/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js new file mode 100644 index 0000000..dabe330 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/__tests__/linked-list.test.js @@ -0,0 +1,235 @@ +const LinkedList = require('../linked-list.js'); + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +describe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +describe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +describe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +describe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +describe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +describe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +describe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +describe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +describe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +describe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list +describe('Can successfully insert a node after last node of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'blue'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('green should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('green'); + }); + it('blue should be in the middle', ()=>{ + expect(list.head.next.data).toBe('blue'); + }); +}); + +// Where k is greater than the length of the linked list +describe(' Where k is greater than the length of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + let k = list.kthFromEnd(3); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + + +// Where k and the length of the list are the same +describe('Where k and the length of the list are the same', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(2); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + +// Where k is not a positive integer +describe('Where k is not a positive integer', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(-3); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return an error message', ()=>{ + expect(k).toBe('k needs to be a postive integer'); + }); +}); +// Where the linked list is of a size 1 +describe('Where the linked list is of a size 1', ()=>{ + let list = new LinkedList(); + list.insert('green'); + let k = list.kthFromEnd(0); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('k should return green', ()=>{ + expect(k).toBe('green'); + }); +}); +// Where k is not at the end, but somewhere in the middle of the linked list +describe('Where k is not at the end, but somewhere in the middle of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('blue'); + list.insert('yellow'); + let k = list.kthFromEnd(1); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return blue', ()=>{ + expect(k).toBe('blue'); + }); +}); \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/linked-list.js b/Data-Structures/ll-kth-from-end/linked-list.js new file mode 100644 index 0000000..c92ec34 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/linked-list.js @@ -0,0 +1,107 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/node.js b/Data-Structures/ll-kth-from-end/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-kth-from-end/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-kth-from-end/readme.md b/Data-Structures/ll-kth-from-end/readme.md new file mode 100644 index 0000000..6e5631d --- /dev/null +++ b/Data-Structures/ll-kth-from-end/readme.md @@ -0,0 +1,31 @@ +# Singly Linked List with K-th Search Method + +More complex functions for singly linked lists + +## Challenge + +Write a method for the LinkedList class which takes a number, k, as a parameter. Return the node’s value that is k from the end of the linked list. You have access to the Node class and all the properties on the LinkedList class as well as the methods created in previous challenges. + +#### Write tests to prove the following functionality: + +* Can successfully add a node to the end of the linked list +* Can successfully add multiple nodes to the end of a linked list +* Can successfully insert a node before a node located in the middle of a linked list +* Can successfully insert a node before the first node of a linked list +* Can successfully insert after a node in the middle of the linked list +* Can successfully insert a node after the last node of the linked list + +## Approach & Efficiency + +O(n) +We never go deeper than one interation of the list so Big O(n) is still applicable + +## API + +insert(data) - Creates a new Node Object. Appends the new Node object to the beginning of the linked list +includes(searchValue) - Takes in a value as a paramenter and returns a boolean if the value exists in the linked list +toString() - Returns a string with all the values in the linked list +append(data) - Adds a node to the end of the list +insertBefore(data, before) - Adds a Node before a certain Node in the list +insertAfter(data, after) - Adds a Node after a certain Node in the list +kthFromEnd(k) - returns the value of a node at the kth index \ No newline at end of file diff --git a/Data-Structures/ll-merge/__tests__/ll-merge.test.js b/Data-Structures/ll-merge/__tests__/ll-merge.test.js new file mode 100644 index 0000000..600449c --- /dev/null +++ b/Data-Structures/ll-merge/__tests__/ll-merge.test.js @@ -0,0 +1,313 @@ +const LinkedList = require('../ll-merge.js'); + +xdescribe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// * Can successfully instantiate an empty linked list +xdescribe('instantiate an empty linked list', ()=>{ + let list = new LinkedList(); + it('empty list',()=>{ + expect(list).toBeTruthy(); + }); +}); + +// * Can properly insert into the linked list +xdescribe('insert into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + + it('successfully inserts into list', ()=>{ + expect(list.head.data).toBe('yellow'); + + }); + +}); +// * The head property will properly point to the first node in the linked list +xdescribe('The head property will properly point to the first node in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('first node is correct', ()=>{ + expect(list.head.data).toBe('blue'); + }); + +}); +// * Can properly insert multiple nodes into the linked list +xdescribe('Can properly insert multiple nodes into the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + + it('successfully added head', ()=>{ + expect(list.head.data).toBe('blue'); + }); + it('successfully added 2nd value', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); + +xdescribe('Will return true when finding a value within the linked list that exists', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + let searchResult = list.includes('yellow'); + let badSearchResult = list.includes('apple'); + + // Will return true when finding a value within the linked list that exists + it('Returns true for items that exist', ()=>{ + expect(searchResult).toBeTruthy(); + }); + // * Will return false when searching for a value in the linked list that does not exist + it('Returns false for items that do not exist', ()=>{ + expect(badSearchResult).toBeFalsy(); + }); +}); + + +// * Can properly return a collection of all the values that exist in the linked list +xdescribe('Can properly return a collection of all the values that exist in the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.insert('blue'); + list.insert('green'); + let allItems = list.toString(); + it('returns a collection', ()=>{ + expect(allItems).toBe('green,blue,yellow'); + }); + +}); + +// Can successfully add a node to the end of the linked list +xdescribe('Can successfully add a node to the end of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('green'); + list.append('blue'); + + it('Items should be added to the end of the list', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + // Can successfully add multiple nodes to the end of a linked list + it('Can add multiple nodes to the end of a list',()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + +}); + +// Can successfully insert a node before a node located in the middle of a linked list + +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'blue'); + it('inserts in middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should stay the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); +}); +// Can successfully insert a node before the first node of a linked list +xdescribe('Can successfully insert a node before a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertBefore('green', 'yellow'); + it('inserts at the head', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('head should move over', ()=>{ + expect(list.head.next.data).toBe('yellow'); + }); +}); +// Can successfully insert after a node in the middle of the linked list +xdescribe('Can successfully insert a node after a node located in the middle of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'yellow'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('blue should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('blue'); + }); + it('new node should be in the middle', ()=>{ + expect(list.head.next.data).toBe('green'); + }); +}); +// Can successfully insert a node after the last node of the linked list +xdescribe('Can successfully insert a node after last node of a linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + list.append('blue'); + list.insertAfter('green', 'blue'); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('green should be at the end', ()=>{ + expect(list.head.next.next.data).toBe('green'); + }); + it('blue should be in the middle', ()=>{ + expect(list.head.next.data).toBe('blue'); + }); +}); + +// Where k is greater than the length of the linked list +xdescribe(' Where k is greater than the length of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('yellow'); + let k = list.kthFromEnd(3); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + + +// Where k and the length of the list are the same +xdescribe('Where k and the length of the list are the same', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(2); + + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return error', ()=>{ + expect(k).toBe('error'); + }); +}); + +// Where k is not a positive integer +xdescribe('Where k is not a positive integer', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('yellow'); + let k = list.kthFromEnd(-3); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return an error message', ()=>{ + expect(k).toBe('k needs to be a postive integer'); + }); +}); +// Where the linked list is of a size 1 +xdescribe('Where the linked list is of a size 1', ()=>{ + let list = new LinkedList(); + list.insert('green'); + let k = list.kthFromEnd(0); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('green'); + }); + it('k should return green', ()=>{ + expect(k).toBe('green'); + }); +}); +// Where k is not at the end, but somewhere in the middle of the linked list +xdescribe('Where k is not at the end, but somewhere in the middle of the linked list', ()=>{ + let list = new LinkedList(); + list.insert('green'); + list.insert('blue'); + list.insert('yellow'); + let k = list.kthFromEnd(1); + it('head stays the same', ()=>{ + expect(list.head.data).toBe('yellow'); + }); + it('k should return blue', ()=>{ + expect(k).toBe('blue'); + }); +}); + +// Where list1 is the same length as list2 +xdescribe('Where list1 is the same length as list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list1.append('2'); + list2.insert('a'); + list2.append('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + expect(merged.head.next.next.data).toBe('2'); + expect(merged.head.next.next.next.data).toBe('b'); + }); +}); +// Where list1 is shorter than list2 +xdescribe('Where list1 is shorter than list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list2.insert('a'); + list2.append('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('a'); + expect(merged.head.next.data).toBe('1'); + expect(merged.head.next.next.data).toBe('b'); + }); +}); +// Where list1 is longer than list2 +xdescribe('Where list1 is longer than list2', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list1.append('2'); + list2.insert('a'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + expect(merged.head.next.next.data).toBe('2'); + }); +}); +// Where list1 is null +xdescribe('Where list1 is null', ()=>{ + let list1 = null; + let list2 = new LinkedList(); + list2.insert('a'); + list2.insert('b'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged).toBe('Not valid Linked List'); + }); +}); +// Where both lists are of length 1 +xdescribe('Where both lists are of length 1', ()=>{ + let list1 = new LinkedList(); + let list2 = new LinkedList(); + list1.insert('1'); + list2.insert('a'); + let merged = new LinkedList(); + merged = merged.mergeLists(list1, list2); + + it('should return an alternating list', ()=>{ + expect(merged.head.data).toBe('1'); + expect(merged.head.next.data).toBe('a'); + }); +}); \ No newline at end of file diff --git a/Data-Structures/ll-merge/ll-merge.js b/Data-Structures/ll-merge/ll-merge.js new file mode 100644 index 0000000..9f5cd64 --- /dev/null +++ b/Data-Structures/ll-merge/ll-merge.js @@ -0,0 +1,141 @@ +const Node = require('./node.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + mergeLists(list1, list2){ + if(list1 === null || list2 === null){ + return 'Not valid Linked List'; + } + let array1 = list1.toString().split(','); + let array2 = list2.toString().split(','); + let final = new LinkedList; + if (array1.length - array2.length > 1 || array2.length - array1.length > 1){ + return 'Linked Lists are not close enough in length'; + } + if (array1.length >= array2.length) { + let answer = []; + for(let i = 0; i < array1.length; i++) { + answer.push([array1[i], array2[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + if (array1.length < array2.length){ + let answer = []; + for(let i = 0; i < array2.length+1; i++){ + answer.push([array2[i], array1[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + return null; + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/ll-merge/node.js b/Data-Structures/ll-merge/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/ll-merge/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/ll-merge/readme.md b/Data-Structures/ll-merge/readme.md new file mode 100644 index 0000000..b3d3bf3 --- /dev/null +++ b/Data-Structures/ll-merge/readme.md @@ -0,0 +1,18 @@ +# Merging two Singly Linked Lists + + + +## Challenge + +* Write a method called mergeLists which takes two linked lists as arguments +* Merge the two lists together such that the final linked list has nodes that alternate between the nodes from each source list +* Return the head of the new merged list +* You have access to the Node class and all the properties on the Linked List class as well as the methods created in previous challenges. + +## Approach & Efficiency + + + +## API + + diff --git a/Data-Structures/stacksAndQueues/__tests__/stacks-and-queues.test.js b/Data-Structures/stacksAndQueues/__tests__/stacks-and-queues.test.js new file mode 100644 index 0000000..c56c9df --- /dev/null +++ b/Data-Structures/stacksAndQueues/__tests__/stacks-and-queues.test.js @@ -0,0 +1,137 @@ +const StackAndQueues = require('../stacks-and-queues.js'); + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); + +// Can successfully push onto a stack +describe('Can successfully push onto a stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + it('adds to the stack', ()=>{ + expect(stack.top.data).toBe('a'); + }); + +}); +// Can successfully push multiple values onto a stack +describe('Can successfully push multiple values onto a stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + it('should be b', ()=>{ + expect(stack.top.data).toBe('b'); + }); + it('should be a', ()=>{ + expect(stack.top.next.data).toBe('a'); + }); +}); +// Can successfully pop off the stack +describe('Can successfully pop off the stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + stack.pop(); + it('should be a', ()=>{ + expect(stack.top.data).toBe('a'); + }); + it('returns pop value', ()=>{ + expect(stack.pop()).toBe('a'); + }); +}); + +// Can successfully empty a stack after multiple pops +describe('Can successfully empty a stack after multiple pops', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + stack.pop(); + stack.pop(); + it('should be a', ()=>{ + expect(stack.top).toBe(null); + }); +}); +// Can successfully peek the next item on the stack +describe('Can successfully peek the next item on the stack', ()=>{ + let stack = new StackAndQueues.Stack(); + stack.push('a'); + stack.push('b'); + let peekItem= stack.peek(); + + it('should be b', ()=>{ + expect(stack.top.data).toBe('b'); + }); + it('should be a', ()=>{ + expect(stack.top.next.data).toBe('a'); + }); + it('Peeked item should be b', ()=>{ + expect(peekItem).toBe('b'); + }); +}); +// Can successfully instantiate an empty stack +describe('Can successfully instantiate an empty stack', ()=>{ + let stack = new StackAndQueues.Stack(); + it('empty stack', ()=>{ + expect(stack.top).toBe(null); + }); +}); +// Can successfully enqueue into a queue +describe('Can successfully enqueue into a queue', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + it('Can successfully enqueue into a queue', ()=>{ + expect(queue.front.data).toBe('a'); + }); + // Can successfully enqueue multiple values into a queue + it('Can successfully enqueue multiple values into a queue', ()=>{ + expect(queue.front.data).toBe('a'); + expect(queue.front.next.data).toBe('b'); + expect(queue.rear.data).toBe('c'); + }); +}); + +// Can successfully dequeue out of a queue the expected value +describe('Can successfully dequeue out of a queue the expected value', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + + it('Can successfully dequeue', ()=>{ + expect(queue.dequeue()).toBe('a'); + }); +}); +// Can successfully peek into a queue, seeing the expected value +describe('Can successfully dequeue out of a queue the expected value', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.enqueue('c'); + + it('Can successfully dequeue', ()=>{ + expect(queue.peek()).toBe('a'); + }); +}); +// Can successfully empty a queue after multiple dequeues +describe('Can successfully empty a queue after multiple dequeues', ()=>{ + let queue = new StackAndQueues.Queue(); + queue.enqueue('a'); + queue.enqueue('b'); + queue.dequeue(); + queue.dequeue(); + + it('Can successfully dequeue', ()=>{ + expect(queue.front).toBe(null); + }); +}); +// Can successfully instantiate an empty queue +describe('Can successfully instantiate an empty queue', ()=>{ + let queue = new StackAndQueues.Queue(); + + it('ITS ALIVE!', ()=>{ + expect(queue.front).toBe(null); + }); +}); \ No newline at end of file diff --git a/Data-Structures/stacksAndQueues/linked-list.js b/Data-Structures/stacksAndQueues/linked-list.js new file mode 100644 index 0000000..0c095b6 --- /dev/null +++ b/Data-Structures/stacksAndQueues/linked-list.js @@ -0,0 +1,141 @@ +const Node = require('./node.js.js'); + +// instantiate an empty linked list +class LinkedList { + constructor(){ + this.head = null; + } + // insert item into the beginning of the list + insert(data){ + let inserted = new Node(data); + inserted.next = this.head; + this.head = inserted; + return this.head; + } + // A function called includes which takes in a value and returns a boolean if that value exists in the linked list + includes(searchValue) { + let currentNode = this.head; + while(currentNode) { + if (currentNode.data === searchValue){ + return true; + } + currentNode = currentNode.next; + } + return false; + } + // A function called toString which takes in no arguments and returns a string representing all the values in the linked list + toString(){ + let stringList = []; + let currentNode = this.head; + while(currentNode){ + stringList.push(currentNode.data); + currentNode = currentNode.next; + } + return stringList.toString(); + + } + // A function called append which adds a Node to the end of the list + append(data){ + let appendedItem = new Node(data); + let currentNode = this.head; + if(this.head === null){ + this.head = appendedItem; + return this.head; + } else{ + while(currentNode.next){ + currentNode = currentNode.next; + } + currentNode.next = appendedItem; + } + } + insertBefore(data, before){ + let insertedItem = new Node(data); + let currentNode = this.head; + if(currentNode.data === before){ + this.insert(data); + return; + } + + while(currentNode.next){ + if(currentNode.next.data === before){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + insertAfter(data, after){ + let insertedItem = new Node(data); + let currentNode = this.head; + + while(currentNode){ + if(currentNode.data === after){ + insertedItem.next = currentNode.next; + currentNode.next = insertedItem; + return; + } + currentNode = currentNode.next; + } + + } + + kthFromEnd(k){ + let listArray = []; + let currentNode = this.head; + while(currentNode){ + listArray.push(currentNode.data); + currentNode = currentNode.next; + } + if(k < 0){ + return 'k needs to be a postive integer'; + } + let kIndex = ((listArray.length - 1) - k); + if(kIndex < 0){ + return 'error'; + } else { + return listArray[kIndex]; + } + } + mergeLists(list1, list2){ + if(list1 === null || list2 === null){ + return 'Not valid Linked List'; + } + let array1 = list1.toString().split(','); + let array2 = list2.toString().split(','); + let final = new LinkedList; + if (array1.length - array2.length > 1 || array2.length - array1.length > 1){ + return 'Linked Lists are not close enough in length'; + } + if (array1.length >= array2.length) { + let answer = []; + for(let i = 0; i < array1.length; i++) { + answer.push([array1[i], array2[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + if (array1.length < array2.length){ + let answer = []; + for(let i = 0; i < array2.length+1; i++){ + answer.push([array2[i], array1[i]]); + answer = [].concat.apply([], answer); + } + answer.forEach(item=>{ + final.append(item); + }); + return final; + } + return null; + } + + +} + + +module.exports = LinkedList; \ No newline at end of file diff --git a/Data-Structures/stacksAndQueues/node.js b/Data-Structures/stacksAndQueues/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/Data-Structures/stacksAndQueues/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/stacksAndQueues/readme.md b/Data-Structures/stacksAndQueues/readme.md new file mode 100644 index 0000000..8543423 --- /dev/null +++ b/Data-Structures/stacksAndQueues/readme.md @@ -0,0 +1,49 @@ +# Stacks and Queues + +Implement a Stack and a Queue Data Structure +[Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/builds/134682110) + +## Challenge + +* Can successfully push onto a stack +* Can successfully push multiple values onto a stack +* Can successfully pop off the stack +* Can successfully empty a stack after multiple pops +* Can successfully peek the next item on the stack +* Can successfully instantiate an empty stack +* Can successfully enqueue into a queue +* Can successfully enqueue multiple values into a queue +* Can successfully dequeue out of a queue the expected value +* Can successfully peek into a queue, seeing the expected value +* Can successfully empty a queue after multiple dequeues +* Can successfully instantiate an empty queue + +## Approach & Efficiency +Stack: +* push O(1) we only manipulate the first item in the stack +* pop O(1) we only manipulate the first item in the stack +* peek O(1) we only manipulate the first item in the stack + +Queue: +* enqueue O(1) we only manipulate one item in the stack +* dequeue O(1) we only manipulate one item in the stack +* peek O(1) we only manipulate one item in the stack +## API +`class Stack { + constructor(){ + this.top = null; + } + push(value) + pop() + peek() +}` + +`class Queue { + constructor(){ + this.front = null; + this.rear = null; + } + enqueue(value) + dequeue() + peek() +}` diff --git a/Data-Structures/stacksAndQueues/stacks-and-queues.js b/Data-Structures/stacksAndQueues/stacks-and-queues.js new file mode 100644 index 0000000..53d7d8b --- /dev/null +++ b/Data-Structures/stacksAndQueues/stacks-and-queues.js @@ -0,0 +1,78 @@ +'use strict'; +const Node = require('./node.js'); + +class Stack { + constructor(){ + this.top = null; + } + push(value){ + if(value !== null){ + let newItem = new Node(value); + if(this.top !== null){ + newItem.next = this.top; + this.top = newItem; + } else { + this.top = newItem; + } + + } else { + return 'bad value'; + } + } + pop(){ + if(this.top !== null){ + this.temp = this.top; + this.top = this.temp.next; + return this.temp.data; + } else { + return 'null'; + } + } + peek(){ + if(this.top !== null){ + return this.top.data; + }else{ + return 'no data!'; + } + + } +} + +class Queue { + constructor(){ + this.front = null; + this.rear = null; + } + enqueue(value){ + if(value !== null){ + let newItem = new Node(value); + if(this.rear === null){ + this.rear = newItem; + this.front = newItem; + }else{ + this.rear.next = newItem; + this.rear = newItem; + } + }else{ + return 'bad value'; + } + } + dequeue(){ + if(this.front !== null){ + this.temp = this.front; + this.front = this.temp.next; + return this.temp.data; + }else{ + return 'null'; + } + } + peek(){ + if(this.front !== null){ + return this.front.data; + }else{ + return 'empty queue'; + } + } +} + +module.exports = { Stack, Queue}; \ No newline at end of file diff --git a/Data-Structures/tree/README.md b/Data-Structures/tree/README.md new file mode 100644 index 0000000..7a8122f --- /dev/null +++ b/Data-Structures/tree/README.md @@ -0,0 +1,15 @@ +# Trees + + + +## Challenge + + + +## Approach & Efficiency + + + +## API + + + +## Whiteboard + + + +## Challenge + + + +## Approach & Efficiency + + + +## API diff --git a/Data-Structures/tree/max-Binary-Tree/__tests__/find-maximum-binary-tree.test.js b/Data-Structures/tree/max-Binary-Tree/__tests__/find-maximum-binary-tree.test.js new file mode 100644 index 0000000..9a23944 --- /dev/null +++ b/Data-Structures/tree/max-Binary-Tree/__tests__/find-maximum-binary-tree.test.js @@ -0,0 +1,6 @@ +describe('Test', () => { + // How might we repeat this to check on types? + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); \ No newline at end of file diff --git a/Data-Structures/tree/max-Binary-Tree/find-maximum-binary-tree.js b/Data-Structures/tree/max-Binary-Tree/find-maximum-binary-tree.js new file mode 100644 index 0000000..eb109ab --- /dev/null +++ b/Data-Structures/tree/max-Binary-Tree/find-maximum-binary-tree.js @@ -0,0 +1,2 @@ +'use strict'; + diff --git a/Data-Structures/tree/node.js b/Data-Structures/tree/node.js new file mode 100644 index 0000000..ebbeec3 --- /dev/null +++ b/Data-Structures/tree/node.js @@ -0,0 +1,12 @@ + +'use strict'; + +class Node { + constructor(value) { + this.data = value; + this.left = null; + this.right = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/Data-Structures/tree/tests/tree.test.js b/Data-Structures/tree/tests/tree.test.js new file mode 100644 index 0000000..141fe3a --- /dev/null +++ b/Data-Structures/tree/tests/tree.test.js @@ -0,0 +1,42 @@ +// const BinarySearchTree = require('../binary-search.js'); +const BinaryTree = require('../tree.js'); + + +xdescribe('Binary Search Tree', () => { + it('Can successfully instantiate an empty tree', () => { + let tree = new BinaryTree; + expect(tree).toBeTruthy(); + }); + + it('Can successfully instantiate a tree with a single root node', () => { + let tree = new BinaryTree; + tree.add(5); + expect(tree.root.data).toBe(5); + }); + + it('Can successfully add a left child and right child to a single root node on a Binary Search Tree', () => { + let tree = new BinaryTree; + tree.add(5); + tree.add(7); + tree.add(2); + expect(tree.root.data).toBe(5); + expect(tree.root.left.data).toBe(2); + expect(tree.root.right.data).toBe(7); + }); +}); +xdescribe('Search Tree', () => { + let tree = new BinaryTree; + tree.add(2); + tree.add(1); + tree.add(3); + console.log(tree.preOrder()); + it('Can successfully return a collection from a pre-order traversal', () => { + expect(tree.preOrder()).toBeTruthy(); + }); +}); +// Can successfully instantiate an empty tree +// Can successfully instantiate a tree with a single root node +// Can successfully return a collection from a pre-order traversal +// Can successfully return a collection from an in-order traversal +// Can successfully return a collection from a post-order traversal +// Can successfully add a left child and right child to a single root node on a Binary Search Tree \ No newline at end of file diff --git a/Data-Structures/tree/tree.js b/Data-Structures/tree/tree.js new file mode 100644 index 0000000..bf8c370 --- /dev/null +++ b/Data-Structures/tree/tree.js @@ -0,0 +1,129 @@ +'Use Strict'; +const Node = require('./node.js'); + +class BinaryTree { + // A root property that stores a Node representing the start of the tree + constructor() { + this.root = null; + } + // A preOrder method that traverses the tree using the pattern root >> left >> right and returns an array of the traversed values + + preOrder() { + let treeRoot = this.root; + let array = []; + array.push(treeRoot.data); + + if (treeRoot.left) { + + + array.push(...treeRoot.left.preOrder()); + + } + + if (treeRoot.right) { + array.push(...treeRoot.right.preOrder()); + } + return array; + } + + inOrder() { + let treeRoot = this.root; + let array = []; + + if (treeRoot.left) { + array.push(...treeRoot.left.inOrder()); + } + + array.push(treeRoot.value); + + if (treeRoot.right) { + array.push(...treeRoot.right.inOrder()); + } + return array; + } + + postOrder() { + let treeRoot = this.root; + let array = []; + + if (treeRoot.left) { + array.push(...treeRoot.left.postOrder()); + } + + if (treeRoot.right) { + array.push(...treeRoot.right.postOrder()); + } + + array.push(treeRoot.value); + return array; + + } + +} + +class BinarySearchTree extends BinaryTree { + add(value) { + let node = this.root; + + // if a root does not exist + // set node as root + if(!node) { + this.root = new Node(value); + return; + } + else { + const search = function(node) { + // if the value is less than the root + // checking node.left + if(value < node.data) { + if(node.left === null) { + node.left = new Node(value); + return; + } + else { + return search(node.left); + } + } + + // if value is greater than the root + // checking node.right + else if (value > node.data) { + if(node.right === null) { + node.right = new Node(value); + return; + } + else { + return search(node.right); + } + } else { + return null; + } + }; + + return search(node); + } + } + + contains(value) { + let current = this.root; + while(current) { + if(value === current.data) { + return true; + } + if(value < current.data) { + current= current.left; + } + else { + current = current.right; + } + } + + return false; + } +} + +module.exports = BinarySearchTree; + + +// An inOrder method that traverses the tree using the pattern left >> root >> right and returns an array of the traversed values +// A postOrder method that traverses the tree using the pattern left >> right >> root and returns an array of the traversed values \ No newline at end of file diff --git a/README.md b/README.md index f2dd06e..ef13bc3 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,42 @@ # data-structures-and-algorithms ## Table of Contents +#### Challenge 1 +[1. Array-Reverse](./challenges/arrayReverse) +#### Challenge 2 +[2. Array-Shift](./challenges/ArrayShift) +#### Challenge 3 +[Array-Binary-Search](./challenges/arrayBinarySearch) +#### Challenge 5 +[Link-List](./Data-Structures/LinkList) +#### Challenge 6 +[ll-Insertions](./Data-Structures/ll-Insertions) +#### Challenge 7 +[ll-kth-from-end](./Data-Structures/ll-kth-from-end) +#### Challenge 8 +[ll-merge](./Data-Structures/ll-merge) +#### Challenge 9 +[Stack-And-Queue](./stacksAndQueues/) +#### Challenge 12 +[fifo-animal-shelter](./challenges/fifoAnimalShelter) +#### Challenge 14 +[] +#### Challenge 15 +[] +#### Challenge 16 +[] +#### Challenge 17 +[] +#### Challenge 18 +[] +#### Challenge 19- Insertion Sort +[Insertion-Sort](./Data-Structures/Sorting/InsertionSort) +#### Challenge 20 +[merge-sort](./Data-Structures/Sorting/MergeSort) +#### Challenge 21 +[merge-sort](./Data-Structures/Sorting/quicksort) +#### Challenge 25 +[Repeated-Word](.challenges/repeatedWord) +#### Challenge 26 -[Array-Reverse](./challenges/arrayReverse) \ No newline at end of file +#### Challenge 27 +[treeIntersection](.challenges/treeIntersection) \ No newline at end of file diff --git a/assets/AWS-1.png b/assets/AWS-1.png new file mode 100644 index 0000000..fdccb7a Binary files /dev/null and b/assets/AWS-1.png differ diff --git a/assets/ArrayShift.jpg b/assets/ArrayShift.jpg new file mode 100644 index 0000000..af68296 Binary files /dev/null and b/assets/ArrayShift.jpg differ diff --git a/assets/CodeChallenge3.jpg b/assets/CodeChallenge3.jpg new file mode 100644 index 0000000..01dea63 Binary files /dev/null and b/assets/CodeChallenge3.jpg differ diff --git a/assets/aws terminal.png b/assets/aws terminal.png new file mode 100644 index 0000000..7336956 Binary files /dev/null and b/assets/aws terminal.png differ diff --git a/challenges/ArrayShift/README.md b/challenges/ArrayShift/README.md new file mode 100644 index 0000000..243916b --- /dev/null +++ b/challenges/ArrayShift/README.md @@ -0,0 +1,11 @@ +# Challenge Summary +insertShiftArray is a function which takes in an array and the value to be added. Without utilizing any of the built-in methods available to javascript, it return an array with the new value added at the middle index. + +## Challenge Description +Write a function called insertShiftArray which takes in an array and the value to be added. Without utilizing any of the built-in methods available to your language, return an array with the new value added at the middle index. + +## Approach & Efficiency +O(N) + +## Solution +![UML](../../assets/ArrayShift.jpg) diff --git a/challenges/ArrayShift/__tests__/array-shift.test.js b/challenges/ArrayShift/__tests__/array-shift.test.js new file mode 100755 index 0000000..5bd253c --- /dev/null +++ b/challenges/ArrayShift/__tests__/array-shift.test.js @@ -0,0 +1,19 @@ +'use strict'; + +const arrayShift = require('../array-shift.js'); + + +xdescribe('Testing challenge', () => { + it('return an array with the new value added at the middle index', () => { + expect(arrayShift([2,4,6,8], 5)).toStrictEqual([2, 4, 5, 6, 8]); + expect(arrayShift([4,8,15,23,42], 16).length).toStrictEqual(4,8,15,16, 23,42); + }); + +}); + +xdescribe('Test', () => { + // How might we repeat this to check on types? + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); diff --git a/challenges/ArrayShift/array-shift.js b/challenges/ArrayShift/array-shift.js new file mode 100644 index 0000000..a53a1a9 --- /dev/null +++ b/challenges/ArrayShift/array-shift.js @@ -0,0 +1,32 @@ +'use strict'; +const arrayShift = {}; + +arrayShift.insertShiftArray = (a, b)=>{ + let answer = []; + let middle = 0; + if(a.length % 2 === 0){ + middle = (a.length / 2); + } else { + middle = ((a.length + 1) / 2); + } + for (let i=0; i< middle; i++){ + answer[i] = a[i]; + } + answer[middle]= b; + for (let i=middle; i< a.length; i++){ + answer[i+1] = a[i]; + } + return answer; +}; + + + +// let test1 = [2,4,6,8]; +// let test1Insert = 5; + +// let test2 = [4,8,15,23,42]; +// let test2Insert = 16; +// console.log('test 1 ', insertShiftArray(test1, test1Insert)); +// console.log('test 2 ', insertShiftArray(test2, test2Insert)); + +module.exports = arrayShift; \ No newline at end of file diff --git a/challenges/arrayBinarySearch/README.md b/challenges/arrayBinarySearch/README.md new file mode 100644 index 0000000..196a990 --- /dev/null +++ b/challenges/arrayBinarySearch/README.md @@ -0,0 +1,18 @@ +# Author: +Morgan Shaw +Nadya Ilinskaya +James Dunn + +# Binary Search +A function called BinarySearch which takes in 2 parameters: a sorted array and the search key. It returns the index of the array’s element that is equal to the search key, or -1 if the element does not exist. + +## Challenge +Write a function called BinarySearch which takes in 2 parameters: a sorted array and the search key. Without utilizing any of the built-in methods available to your language, return the index of the array’s element that is equal to the search key, or -1 if the element does not exist. + +## Approach & Efficiency +While loop through the array: Find the middle of the array. Compare the value that is located at the index = middle to the search key. Because the array is sorted we can determine to change our search parameters to the left or the right of the array. Once the index is found return the index, if the key does not exist in the array return -1. + +## Solution +[link](./array-binary-search.js) +[Repl.it](https://repl.it/repls/OrneryCurlyDividend) +![UML Diagram](../../assets/CodeChallenge3.jpg) \ No newline at end of file diff --git a/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js b/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js new file mode 100755 index 0000000..16f7979 --- /dev/null +++ b/challenges/arrayBinarySearch/__tests__/arrayBinary.test.js @@ -0,0 +1,17 @@ +'use strict'; +const BinarySearch = require('../array-binary-search.js'); +xdescribe('Testing challenge', () => { + + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23], 15)).toStrictEqual(2); + }); + it('it should return -1 if the search key does not exist', () => { + expect(BinarySearch([11,22,33,44,55,66,77], 90)).toStrictEqual(-1); + }); + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23,42,90], 8)).toStrictEqual(1); + }); + it('it should return the index of the array’s element that is equal to the search key', () => { + expect(BinarySearch([4,8,15,16,23,42], 42)).toStrictEqual(5); + }); +}); \ No newline at end of file diff --git a/challenges/arrayBinarySearch/array-binary-search.js b/challenges/arrayBinarySearch/array-binary-search.js new file mode 100644 index 0000000..cb87de5 --- /dev/null +++ b/challenges/arrayBinarySearch/array-binary-search.js @@ -0,0 +1,25 @@ +'Use Strict'; + +//this is the function that will search an array for a given input +const BinarySearch = (arr, search)=>{ + //check if middle index matches key + let firstIndex = 0; + let lastIndex = arr.length - 1; + while (firstIndex <= lastIndex) { + let middle = Math.floor((firstIndex + lastIndex) / 2); + if (arr[middle] === search) { + return middle; + } + if (arr[middle] > search) { + // if search is less, then firstIndex stays same + // and lastIndex changes to middle minus 1 + lastIndex = --middle; + // divide that by two, and make that new middle + } else if (arr[middle] < search) { + firstIndex = ++middle; + } + } + return -1; +}; + +module.exports = BinarySearch; diff --git a/challenges/fifoAnimalShelter/README.md b/challenges/fifoAnimalShelter/README.md new file mode 100644 index 0000000..8ecf567 --- /dev/null +++ b/challenges/fifoAnimalShelter/README.md @@ -0,0 +1,58 @@ +# Animal Shelter Queue + +## Links + +- [PR](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/10) +- [Link to Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/builds/135561004) + +Build a a Queue that represents an animal shelter. Creat Dog and Cat classes. + +## Challenge + +* Create a Dog and Cat class. These classes should share the following properties: + * `name:` a string representing the name of this animal + * `print():` a function that prints + * `${name}` is a good dog! if this is a Dog object + * `${name}` is a sweet cat! if this is a Cat object +* Create a Queue class called AnimalShelter which holds only Dogs and Cats + * Add a function `enqueue(animal)` which adds the specified Dog or Cat object into the shelter + * Add a function `dequeue(pref)` which dequeues either the first Dog or the first Cat object in the queue, depending on what pref is (pref may be a string that is either empty, 'cat' or 'dog') + * If pref is an empty string, dequeue the first animal in the queue, regardless of if it’s a Dog or Cat + * After you dequeue, call the `print()` function on the dequeued object +## Approach & Efficiency + +print() Big O(1) this does not traverse through the input and only performs a single task +enqueue(animal) Big O(1) this will only add an item to the back of the queue and does not traverse through the entire list. +dequeue(pref) Big O(n) this will potentially go through the entire queue if the pref animal is not actually in the queue. + +## API + +class Dog { + constructor(name){ + this.name = name; + } + + print() +} + +class Cat { + constructor(name){ + this.name = name; + } + + print() + +} + +class AnimalShelter { + constructor(){ + this.front = null; + this.rear = null; + } + + enqueue(animal) + + + dequeue(pref) + +} diff --git a/challenges/fifoAnimalShelter/__tests__/fifo-animal-shelter.test.js b/challenges/fifoAnimalShelter/__tests__/fifo-animal-shelter.test.js new file mode 100644 index 0000000..f6cb6cf --- /dev/null +++ b/challenges/fifoAnimalShelter/__tests__/fifo-animal-shelter.test.js @@ -0,0 +1,79 @@ +const fifoAnimalShelter = require('../fifo-animal-shelter.js'); +const Dog = fifoAnimalShelter.Dog; +const Cat = fifoAnimalShelter.Cat; +const AnimalShelter = fifoAnimalShelter.AnimalShelter; + +describe('Fifo Animal Shelter Tests!', () => { + // Can successfully enqueue a Dog + it('Can successfully enqueue a Dog', ()=>{ + let dog = new Dog('Hachi'); + let home = new AnimalShelter; + home.enqueue(dog); + expect(home.front.data.name).toBe('Hachi'); + }); + // Can successfully enqueue a Cat + it('Can successfully enqueue a Cat', ()=>{ + let cat = new Cat('Luna'); + let home = new AnimalShelter; + home.enqueue(cat); + expect(home.front.data.name).toBe('Luna'); + }); + + // Error handling when you try to enqueue something that is neither a Dog nor a Cat + it('Error handling when you try to enqueue something that is neither a Dog nor a Cat', ()=>{ + let kangaroo = 'yellow kangaroo'; + let home = new AnimalShelter; + expect(home.enqueue(kangaroo)).toBe('Cats & Dogs only!'); + }); + + // Can successfully dequeue a Dog + it('Can successfully dequeue a Dog', ()=>{ + let dog = new Dog('Hachi'); + let cat = new Cat('Luna'); + let home = new AnimalShelter; + home.enqueue(dog); + home.enqueue(cat); + expect(home.dequeue('Dog')).toBe('Hachi is a good dog!'); + }); + + // Can successfully dequeue a Cat + it('Can successfully dequeue a Cat', ()=>{ + let cat = new Cat('Luna'); + let cat2 = new Cat('Mao'); + let dog = new Dog('Hachi'); + let home = new AnimalShelter; + home.enqueue(cat); + home.enqueue(cat2); + home.enqueue(dog); + home.dequeue('Dog'); + expect(home.dequeue('Cat')).toBe('Luna is a sweet cat!'); + }); + + // Can successfully dequeue the front of the AnimalShelter queue when you pass no parameters to dequeue + it('Can successfully dequeue the front of the AnimalShelter queue when you pass no parameters to dequeue', ()=>{ + let cat = new Cat('Luna'); + let dog = new Dog('Hachi'); + let home = new AnimalShelter; + home.enqueue(cat); + home.enqueue(dog); + + expect(home.dequeue()).toBe('Luna is a sweet cat!'); + }); + + // Error handling when you try to dequeue something that is neither a 'cat', 'dog' or an empty string + it('Error handling when you try to dequeue something that is neither a "cat" or "dog" or an empty string', ()=>{ + let cat = new Cat('Luna'); + let home = new AnimalShelter; + home.enqueue(cat); + expect(home.dequeue('lizard')).toBe('we do not have that animal'); + }); + + // Can successfully print the resulting object from a dequeue action + it('Can successfully print the resulting object from a dequeue action', ()=>{ + let cat = new Cat('Luna'); + let home = new AnimalShelter; + home.enqueue(cat); + expect(home.dequeue('Cat')).toBe('Luna is a sweet cat!'); + }); + +}); diff --git a/challenges/fifoAnimalShelter/fifo-animal-shelter.js b/challenges/fifoAnimalShelter/fifo-animal-shelter.js new file mode 100644 index 0000000..c877bdb --- /dev/null +++ b/challenges/fifoAnimalShelter/fifo-animal-shelter.js @@ -0,0 +1,74 @@ +'Use Strict'; +const Node = require('./node.js'); + +class Dog { + constructor(name){ + this.name = name; + } + print(){ + return `${this.name} is a good dog!`; + } +} + +class Cat { + constructor(name){ + this.name = name; + } + print(){ + return `${this.name} is a sweet cat!`; + } +} + +class AnimalShelter { + constructor(){ + this.front = null; + this.rear = null; + } + enqueue(animal){ + let species = animal.constructor.name; + + if(species === 'Cat'|| species === 'Dog'){ + let newItem = new Node(animal); + if(this.rear === null){ + this.rear = newItem; + this.front = newItem; + return; + }else{ + this.rear.next = newItem; + this.rear = newItem; + return; + } + }else{ + return 'Cats & Dogs only!'; + } + } + dequeue(pref){ + + let current = this.front; + + if(current.data.constructor.name === pref || pref === undefined){ + this.temp = this.front; + this.front = this.temp.next; + return this.temp.data.print(); + } + while(current.next){ + if(current.next.data.constructor.name === pref){ + if(current.next === this.rear){ + this.temp = current.next; + current.next= current; + this.rear = current; + return this.temp.data.print(); + } + this.temp = current.next; + current.next = current.next.next; + return this.temp.data.print(); + } + current = current.next; + } + return 'we do not have that animal'; + } +} + + +module.exports = { Dog, Cat, AnimalShelter}; + diff --git a/challenges/fifoAnimalShelter/node.js b/challenges/fifoAnimalShelter/node.js new file mode 100644 index 0000000..ae7d7e9 --- /dev/null +++ b/challenges/fifoAnimalShelter/node.js @@ -0,0 +1,10 @@ +'use strict'; + +class Node { + constructor(value){ + this.data = value; + this.next = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/challenges/repeatedWord/README.md b/challenges/repeatedWord/README.md new file mode 100644 index 0000000..80868d7 --- /dev/null +++ b/challenges/repeatedWord/README.md @@ -0,0 +1,24 @@ +# Repeated Word + +## Links + +- [Link to Pull Request](https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/pull/18) +- [Link to Travis](https://travis-ci.com/morgan-401-advanced-javascript/data-structures-and-algorithms/builds/145075856) +- [replt](https://repl.it/repls/PalatableKnobbyDisks) + +## Whiteboard / Drawing + + + +## Challenge + +Write a function that accepts a lengthy string parameter. +Without utilizing any of the built-in library methods available to your language, return the first word to occur more than once in that provided string. + +## Approach & Efficiency + +Big O(n^2) due to the nested for loops. + +## API + +`repeatedWord` takes in a string as a parameter and returns the first repeated word \ No newline at end of file diff --git a/challenges/repeatedWord/__tests__/repeatedWord.test.js b/challenges/repeatedWord/__tests__/repeatedWord.test.js new file mode 100644 index 0000000..402da81 --- /dev/null +++ b/challenges/repeatedWord/__tests__/repeatedWord.test.js @@ -0,0 +1,39 @@ +'use strict'; +const repeatedWord = require('../repeatedWord'); + +describe('Test', () => { + it('true', ()=>{ + expect(true).toBeTruthy(); + }); +}); +describe('Edge Cases', () => { + // String which contains only one word + it('String which contains only one word', ()=>{ + let oneWord = 'one'; + expect(repeatedWord(oneWord)).toBe('Nothing to compare'); + }); + // String where the repeated word happens immediately (‘hello hello’) + it('String where the repeated word happens immediately (‘hello hello’)', ()=>{ + let immediately = 'hello hello'; + expect(repeatedWord(immediately)).toBe('hello'); + }); + // String where there are no repeated words + it('String where there are no repeated words', ()=>{ + let none = 'no repeated words'; + expect(repeatedWord(none)).toBe('No repeated words'); + }); +}); + +// Incorrect parameter error handling +describe('Incorrect parameter error handling', () => { + // Not a string + it('Not a string', ()=>{ + let numbers = 5; + expect(repeatedWord(numbers)).toBe('Not a string'); + }); + // Empty string + it('Empty string', ()=>{ + let empty = ''; + expect(repeatedWord(empty)).toBe('empty'); + }); +}); \ No newline at end of file diff --git a/challenges/repeatedWord/repeatedWord.js b/challenges/repeatedWord/repeatedWord.js new file mode 100644 index 0000000..927b94a --- /dev/null +++ b/challenges/repeatedWord/repeatedWord.js @@ -0,0 +1,27 @@ +'use strict'; +function repeatedWord(str){ + + if(str.length < 1){ + return 'empty'; + } + if(typeof str !== 'string'){ + return 'Not a string'; + } + + let array= str.split(' '); + let newArray = []; + if(array.length === 1){ + return 'Nothing to compare'; + } + for(let i = 0; i < array.length; i ++){ + for(let j = 0; j { + let test1 = new tree; + test1.add(150); + test1.add(100); + test1.add(75); + test1.add(160); + test1.add(125); + test1.add(175); + test1.add(250); + test1.add(200); + test1.add(350); + test1.add(300); + test1.add(500); + let test2 = new tree; + test2.add(42); + test2.add(100); + test2.add(15); + test2.add(160); + test2.add(125); + test2.add(175); + test2.add(600); + test2.add(200); + test2.add(350); + test2.add(4); + test2.add(500); + + let same = repeated(test1, test2); + + it('It works!', ()=>{ + expect(same).toEqual([100, 125, 160, 175, 200, 350, 500]); + }); + let test3= new tree; + let test4 = new tree; + test3.add(42); + test4.add(40); + // Binary trees with no shared values + it('Binary trees with no shared values', ()=>{ + expect(repeated(test3, test4)).toEqual([]); + }); + // Identical binary trees (all values shared) + let test5= new tree; + let test6 = new tree; + test5.add(42); + test6.add(42); + it(' Identical binary trees (all values shared)', ()=>{ + expect(repeated(test5, test6)).toEqual([42]); + }); + // Binary trees of vastly different sizes (for example, one has just a single node, another has 20 nodes) + it(' Binary trees of vastly different sizes (for example, one has just a single node, another has 20 nodes)', ()=>{ + expect(repeated(test2, test6)).toEqual([42]); + }); + // Incorrect parameter + it('Incorrect parameter', ()=>{ + expect(repeated(5, 'yellow')).toEqual('invalid'); + }); +}); + diff --git a/challenges/treeIntersection/assets/uml.jpg b/challenges/treeIntersection/assets/uml.jpg new file mode 100644 index 0000000..f86d0fb Binary files /dev/null and b/challenges/treeIntersection/assets/uml.jpg differ diff --git a/challenges/treeIntersection/node.js b/challenges/treeIntersection/node.js new file mode 100644 index 0000000..484a833 --- /dev/null +++ b/challenges/treeIntersection/node.js @@ -0,0 +1,11 @@ +'use strict'; + +class Node { + constructor(value) { + this.data = value; + this.left = null; + this.right = null; + } +} + +module.exports = Node; \ No newline at end of file diff --git a/challenges/treeIntersection/tree-intersection.js b/challenges/treeIntersection/tree-intersection.js new file mode 100644 index 0000000..b46351b --- /dev/null +++ b/challenges/treeIntersection/tree-intersection.js @@ -0,0 +1,30 @@ +'use strict'; +const node = require('./node'); +const tree = require('./tree'); + + +function tree_intersection(tree1, tree2){ + if(!tree1.root || !tree2.root){ + return 'invalid'; + } + // loop through tree 1 + let tree1Array = tree1.inOrder(); + let tree2Array = tree2.inOrder(); + + let newArray = []; + + for(let i = 0; i < tree1Array.length; i ++){ + // compare each node to tree2 + for(let j = 0; j { + if(node.left) { + traverse(node.left); + } + result.push(node.data); + if(node.right) { + traverse(node.right); + } + }; + traverse(this.root); + return result; + } +} +class BinarySearchTree extends BinaryTree { + add(value) { + let node = this.root; + if(!node) { + this.root = new Node(value); + return; + } + else { + const search = function(node) { + if(value < node.data) { + if(node.left === null) { + node.left = new Node(value); + return; + } + else { + return search(node.left); + } + } + else if (value > node.data) { + if(node.right === null) { + node.right = new Node(value); + return; + } + else { + return search(node.right); + } + } else { + return null; + } + }; + return search(node); + } + } +} +module.exports = BinarySearchTree; \ No newline at end of file diff --git a/package.json b/package.json index b42cee4..628ee97 100644 --- a/package.json +++ b/package.json @@ -4,13 +4,17 @@ "description": "", "main": "index.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" + "start": "node index.js", + "lint": "eslint \"**/*.js\"", + "test": "jest --verbose --coverage", + "test-watch": "jest --watchAll --verbose --coverage", + "jsdoc": "jsdoc -c ./docs/config/jsdoc.config.json" }, "repository": { "type": "git", "url": "git+https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms.git" }, - "author": "", + "author": "Morgan T Shaw", "license": "ISC", "bugs": { "url": "https://github.com/morgan-401-advanced-javascript/data-structures-and-algorithms/issues"