-
-
-
-
-
-
\ No newline at end of file
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..565fa8c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,6 @@
+language: node_js
+node_js:
+ - "9"
+
+script:
+ - npm test
\ No newline at end of file
diff --git a/README.md b/README.md
index 5ce05db..75fe28f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,7 @@
# data-structures-and-algorithms
+* [travis](https://www.travis-ci.com/MeStock/data-structures-and-algorithms)
+
Overview
This repo is a place to organize completed code challenges. Within the code challenges folder, you can find examples of different data structure and algorithm problems with their optimzed solutions.
@@ -218,3 +220,256 @@ Add in some conditionals for edge cases:
## Solution

+# Reverse an Array
+The reverse array function will take in an array as a parameter and return the elements of the array in reverser order.
+
+## Challenge
+Modify array in place
+
+## Approach & Efficiency
+I knew that I needed some sort of looping mechanism, so I started by visualizing the input and output of the array.
+ I: [1,2,3,4,5]
+ O: [5,4,3,2,1]
+Keeping track of the front index and back index and making swaps was the optimal solution.
+
+LOOP 1:
+[5,2,3,4,1]
+
+LOOP 2:
+[5,4,3,2,1]
+
+LOOP 3: reached the middle of the array so return the current state of the array.
+
+The time complexity for this is O(n) where n is half the length of the list and space complexity is O(1) because we are modifying in place.
+You can also solve this problem using built in array methods (reverse, push, pop) or recursively but the space/time complexities are not as efficient.
+
+## Solution
+
+
+# Find Sum of Integers
+Given an array and key, find the first pair of values within the array that add up and equal the key.
+
+## Challenge
+Modify array in place
+
+## Approach & Efficiency
+I used a hashmap to implement this search. Add all the values to a hashmap. Iterate through array, calculate the difference between each index of the array and the key. Use the hashmap to check if the difference exists within the map.
+
+Time complexity: O(n) where n is the length of the array
+Space complexity: O(n) where n is the length of the array
+
+The brure force method for this problem is to check every single pair within the array using nesed for loops. This would result in time complexity of O(n^2) and space complexity of O(1). Depending on individual cases, you would consider this case to save space.
+
+## Solution
+
+
+# Hashtables
+We mob programmed this challenge. Group members: Melissa Stock, Bonnie Wang, Jagdeep Singh, Rebecca Peterson, Joe Jemmely
+Implement a hashtable with the following built in methods : add(key, value), get(key), contains(key), and hash(key);
+
+## Challenge
+* add(key, value) returns the value that was just added
+* get(key) returns the value associated with the key
+* contains(key) returns true/false if the hashtable contains a value with the associated key
+* hash(key) returns an index associated with the unique hashed key
+
+## Approach & Efficiency
+* add(key, value) Time: O(L) where L is the length of the string Space: O(1) *if you ignore the hashing Time: O(1)
+* get(key) Time: O(L) where L is the length of the string Space: O(1) *if you ignore the hashing Time: O(1)
+* contains(key) Time: O(L) where L is the length of the string Space: O(1) *if you ignore the hashing Time: O(1)
+* hash(key) Time: O(L) where L is the length of the string Space: O(1)
+
+# Find Tree Path
+Given a start and an end value, traverse a tree and return a linked list representation of the path between the start and end value.
+
+## Challenge
+* Traverse the tree
+* Keep track of values
+* Create a linked list of values for the path
+* Add/remove values that belong in path
+
+## Approach & Efficiency
+Broke the problem into several smaller problems listed above to identify an approach. I used recursion to traverse the tree and modified the linked list in place to keep track of values within the given path.
+
+Time complexity: O(H) where H is the height of the tree
+Space complexity: O(n) where n is the length of the linked list
+
+## Solution
+
+
+# Find Intersections Between Two Trees
+Given two binary trees, find all the intersections between the two. Meaning, return all the common values that they share between them.
+
+## Challenge
+* Traverse tree 1
+ * Add all its values into a set
+ * Return the set
+* Traverse tree 2
+ * At eact node - if the value exists in the previous set
+ * add that value to new set
+ * Return new set
+* Return the new set
+
+## Approach & Efficiency
+Broke the problem into 3 functions listed above. Time complexity O(n) where n is the sum of nodes between the two trees. Space complexity O(m) where m is the the larger of two - either the height of the second tree or the number of nodes in the first tree.
+
+## Solution
+
+
+# Left Join
+Given two hashmaps, join the values of matching keys into the left map. If the key does not exist in the right map, add null to the join. Return a new data structure of the joined key value pairs.
+
+
+Input:
+
+* Map1 = {k1:v1, k2:v2, k3:v3}
+
+* Map2 = {k1:val1, k2:val2, k4:val4}
+
+Output:
+
+* {k1:[v1,val1], k2:[v2,val2], k3:[v3,null]}
+
+## Challenge
+* Iterate through Map1
+ * Add all its key value pairs to a new object where the keys remain the same but the values are added to an array
+ * Check if value exists in Map2
+ * if yes - get that value and add it to the end of the array
+ * if no - add null to the end of the array
+ * return the new object
+
+## Approach & Efficiency
+Time complexity is O(n) where n is number of keys in Map1
+Space complexity is O(n) where n is the sum of the values in Map1 and Map2
+
+
+## Solution
+
+
+# Find Max and Min Zeros
+Given a 2D array of sorted binary values, find the row that has the most and least number of zeros.
+
+
+Input:
+[
+ [0,0,0,1],
+ [0,0,0,1],
+ [0,0,1,1],
+ [0,0,0,1],
+ [0,0,0,0],
+ [0,0,0,1],
+];
+
+Output:
+
+* {max: 4, min: 2}
+
+## Challenge
+* Iterate through all the rows
+ * For each row - find the particition point (where 0 changes to 1) using a binary search
+ * Compare partition point index to the current max & min
+ * The row with the lowest parition point index has the least zeros
+ * THe row with the largest partition point index has the most zeros
+
+## Approach & Efficiency
+Time complexity is O(mlog(n)) m is the number of rows and n is the number of indexies
+Space complexity is O(1) because we are only storing the max & min regarldless of the shape of the input
+
+
+## Solution
+
+
+# Flags & Quicksort
+Give an array with values: blue, white and shield - sort the array so that it represents the el-salvadorian flag. The white and blue values will always be even and there is only one shield.
+
+
+Input:
+['white', 'blue', 'blue', 'white', 'white', 'white', 'shield', 'blue', 'blue'];
+
+Output:
+['blue', 'blue', 'white','white', 'shield', 'white', 'white', 'blue', 'blue'];
+
+
+
+## Challenge
+* Set the pivot to the last value
+ * iterate through array
+ * check if value is blue, white or shield (using switch)
+ * mark firstblue/white depending on each value
+ * if shield is found move it to the center
+ * track how many blues/white are on each side
+ * swap values based on firstblue/white and lastblue/white locations
+
+## Approach & Efficiency
+Time complexity is O(n) n is the number of values within the array
+Space complexity is O(1) because we modifying in place
+
+
+## Solution
+
+
+# Depth First Traveral of a Graph
+Given an adjacency list of a graph, print out the values in preorder.
+
+Input:
+{
+ A: [B,D],
+ B: [C,D,A],
+ C: [G,B],
+ G: [C],
+ D: [E,H,F,A,B],
+ E: [D],
+ H: [F,D],
+ F: [D,H]
+}
+
+Output
+[A,B,C,G,D,E,H,F]
+
+## Challenge
+* Track the visited verticies
+* Starting at the root:
+ * Check the first neighboring vertex
+ * Add its value to the tracked verticies
+ * Check its neighboring vertex & repeat until there is a dead end
+
+## Approach & Efficiency
+Traversing the tree recursively:
+Time complexity is O(n) n is the number of vertecies in the graph
+Space complexity is O(n) where n is the number of vertecies in the graph
+
+## Solution
+
+
+# Depth First Traveral of a Graph
+Given an 8x8 2d array, determine if two chess pieces are within range of the king. Pieces are placed randomly within the 8x8 board.
+
+Input:
+k = King
+b = bishop
+r = rook
+[
+ [0,0,0,0,0,0,0,0],
+ [0,0,r,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0],
+ [0,0,0,0,k,0,0,0],
+ [0,0,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0],
+ [0,b,0,0,0,0,0,0],
+ [0,0,0,0,0,0,0,0]
+]
+
+Output
+True
+
+## Challenge
+* Iterate over the arrays to locate all the pieces
+* calculate if the found pieces can move to the location of the king
+* return true or false
+
+## Approach & Efficiency
+Time Complexity: O(1) because we will always have to traverse over the entire board to locate the pieces
+Space Complexity: O(1) because we will always have to store the same amount of space for the location of each piece.
+
+## Solution
+
\ No newline at end of file
diff --git a/__tests__/append-insert-before-after.test.js b/__tests__/append-insert-before-after.test.js
index b4b355d..d28ae1c 100644
--- a/__tests__/append-insert-before-after.test.js
+++ b/__tests__/append-insert-before-after.test.js
@@ -10,35 +10,35 @@ describe('Linked list', () => {
const test = new LinkedList();
expect(test.append('test')).toEqual(expect.objectContaining(test));
});
- xit('should properly insert before the first node of the list', () => {
- const test = new LinkedList();
- test.append('head');
- test.append('first node');
- test.append('second node');
- test.insertBefore('head','inserted before node');
- expect(test.value).toBe('inserted before node');
- });
- xit('should properly insert before i in the middle of the list', () => {
- const test = new LinkedList();
- test.append('head');
- test.append('first node');
- test.append('second node');
- test.insertBefore('first node','inserted node');
- expect(test.next.value).toEqual('inserted node');
- });
- xit('should properly insert after the last node of the list', () => {
- const test = new LinkedList();
- test.append('head');
- test.append('first node');
- test.insertAfter('first node', 'inserted node');
- expect(test.next.next.value).toEqual('inserted node');
- });
- xit('should properly insert in the middle of the list', () => {
- const test = new LinkedList();
- test.append('head');
- test.append('first node');
- test.append('second node');
- test.insertAfter('first node', 'inserted node');
- expect(test.next.next.value).toEqual('inserted node');
- });
-});
\ No newline at end of file
+ // xit('should properly insert before the first node of the list', () => {
+ // const test = new LinkedList();
+ // test.append('head');
+ // test.append('first node');
+ // test.append('second node');
+ // test.insertBefore('head','inserted before node');
+ // expect(test.value).toBe('inserted before node');
+ // });
+ // xit('should properly insert before i in the middle of the list', () => {
+ // const test = new LinkedList();
+ // test.append('head');
+ // test.append('first node');
+ // test.append('second node');
+ // test.insertBefore('first node','inserted node');
+ // expect(test.next.value).toEqual('inserted node');
+ // });
+ // xit('should properly insert after the last node of the list', () => {
+ // const test = new LinkedList();
+ // test.append('head');
+ // test.append('first node');
+ // test.insertAfter('first node', 'inserted node');
+ // expect(test.next.next.value).toEqual('inserted node');
+ // });
+ // xit('should properly insert in the middle of the list', () => {
+ // const test = new LinkedList();
+ // test.append('head');
+ // test.append('first node');
+ // test.append('second node');
+ // test.insertAfter('first node', 'inserted node');
+ // expect(test.next.next.value).toEqual('inserted node');
+ // });
+});
diff --git a/__tests__/array-reverse.test.js b/__tests__/array-reverse.test.js
new file mode 100644
index 0000000..43f0393
--- /dev/null
+++ b/__tests__/array-reverse.test.js
@@ -0,0 +1,31 @@
+'use strict';
+
+const arrayReverse1 = require('../code-challenges/array-reverse/array-reverse.js').reverseArray;
+const arrayReverse2 = require('../code-challenges/array-reverse/array-reverse.js').stretchGoal;
+const arrayReverse3 = require('../code-challenges/array-reverse/more-array-reverse.js');
+const reversedTest = ['d', 'c', 'b', 'a'];
+
+
+describe('Array Reverse', () => {
+ it('should reverse an array with one element', () => {
+ const test = ['a'];
+ expect(arrayReverse1(test)).toEqual(['a']);
+ expect(arrayReverse2(test)).toEqual(['a']);
+ expect(arrayReverse3(test)).toEqual(['a']);
+ });
+
+ it('should reverse any array of any size', () => {
+ const test1 = ['a', 'b', 'c', 'd'];
+ const test2 = ['a', 'b', 'c', 'd'];
+ const test3 = ['a', 'b', 'c', 'd'];
+ expect(arrayReverse1(test1)).toEqual(reversedTest);
+ expect(arrayReverse2(test2)).toEqual(reversedTest);
+ expect(arrayReverse3(test3)).toEqual(reversedTest);
+ });
+
+ it('should return null if no array is given', () => {
+ expect(arrayReverse1()).toBeNull();
+ expect(arrayReverse2()).toBeNull();
+ expect(arrayReverse3()).toBeNull();
+ });
+});
diff --git a/__tests__/chess.js b/__tests__/chess.js
new file mode 100644
index 0000000..22da434
--- /dev/null
+++ b/__tests__/chess.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const checkChessboard = require('../code-challenges/chess/chess.js');
+
+describe('chess board', () => {
+ it('should return true is the king can be reached', () => {
+ const test = [
+ [0,0, 0, 0,0,0,0,0],
+ [0,0,'r',0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ [0,0,0,0,'k',0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ [0,'b',0,0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0]
+ ];
+ expect(checkChessboard(test)).toBeTruthy;
+ });
+ it('should return false if the king cant be reached', () => {
+ const test = [
+ [0,0, 0, 0,0,0,0,0],
+ [0,0,'r',0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ [0,0,0,0,'k',0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0],
+ ['b',0,0,0,0,0,0,0],
+ [0,0, 0, 0,0,0,0,0]
+ ];
+ expect(checkChessboard(test)).toBeFalsey;
+ });
+ it('should reject invalid inputs', () => {
+ expect(checkChessboard()).toBeNull();
+ expect(checkChessboard([])).toBeNull();
+ expect(checkChessboard([[],[],[]])).toBeNull();
+ });
+});
diff --git a/__tests__/dfs-challenge41.test.js b/__tests__/dfs-challenge41.test.js
new file mode 100644
index 0000000..a189910
--- /dev/null
+++ b/__tests__/dfs-challenge41.test.js
@@ -0,0 +1,20 @@
+'use strict';
+
+const depthFirstTraversal = require('../code-challenges/graph/dfs-challenge41.js');
+
+describe('depth first traversal', () => {
+ const testAdjacencyList = {
+ A: ['B','D'],
+ B: ['C','D','A'],
+ C: ['G','B'],
+ G: ['C'],
+ D: ['E','H','F','A','B'],
+ E: ['D'],
+ H: ['F','D'],
+ F: ['D','H']
+ };
+ const answer = ['A','B','C','G','D','E','H','F'];
+ it('should return a preordered list', () => {
+ expect(Array.from(depthFirstTraversal(testAdjacencyList))).toEqual(answer);
+ });
+});
diff --git a/__tests__/findSumOfInts.test.js b/__tests__/findSumOfInts.test.js
new file mode 100644
index 0000000..c06a452
--- /dev/null
+++ b/__tests__/findSumOfInts.test.js
@@ -0,0 +1,22 @@
+'use strict';
+
+const findSumOfInts = require('../code-challenges/findSumOfInts/findSumOfInts.js');
+
+describe('find sum of integers', () => {
+ it('should find 2 numbers inside an array that add up to the key', () => {
+ const test = [1,4,8,3,7,2,0,-1];
+ expect(findSumOfInts(test, 11)).toEqual([4,7]);
+ });
+
+ it('should return null if inputs are not valid', () => {
+ expect(findSumOfInts()).toBeNull();
+ expect(findSumOfInts(1,2)).toBeNull();
+ expect(findSumOfInts([1,2,3], 'not a number')).toBeNull();
+ expect(findSumOfInts([], 4)).toBeNull();
+ });
+
+ it('should find the first pair that add up to the key', () => {
+ const test = [1,2,4,-1];
+ expect(findSumOfInts(test, 3)).toEqual([1,2]);
+ });
+});
diff --git a/__tests__/findTreeIntersection.test.js b/__tests__/findTreeIntersection.test.js
new file mode 100644
index 0000000..4d50edc
--- /dev/null
+++ b/__tests__/findTreeIntersection.test.js
@@ -0,0 +1,34 @@
+'use strict';
+
+const findTreeIntersection = require('../code-challenges/findTreeIntersection/findTreeIntersection.js');
+const BinaryTree = require('../code-challenges/tree/tree.js');
+const Node = require('../code-challenges/tree/node.js');
+
+describe('Find all intersections within two trees', () => {
+ it('should return a set of common values between the trees', () => {
+ const test1 = new BinaryTree(1);
+ test1.root.right = new Node(2);
+ test1.root.left = new Node(3);
+ const test2 = new BinaryTree(2);
+
+ const answer = new Set();
+ answer.add(2);
+
+ expect(findTreeIntersection(test1, test2)).toEqual(answer);
+ });
+
+ it('should return null if there are invalid inputs', () => {
+ const test = new BinaryTree();
+
+ expect(findTreeIntersection()).toBeNull();
+ expect(findTreeIntersection(test)).toBeNull();
+ });
+
+ it('should return an empty set if no common values are found', () => {
+ const test1 = new BinaryTree(1);
+ const test2 = new BinaryTree(2);
+
+ expect(findTreeIntersection(test1, test2)).toEqual(new Set());
+ });
+
+});
diff --git a/__tests__/findTreePath.test.js b/__tests__/findTreePath.test.js
new file mode 100644
index 0000000..019ad10
--- /dev/null
+++ b/__tests__/findTreePath.test.js
@@ -0,0 +1,53 @@
+'use strict';
+const BTnode = require('../code-challenges/tree/node.js');
+const BinaryTree = require('../code-challenges/tree/tree.js');
+const findTreePath = require('../code-challenges/findTreePath/findTreePath.js');
+const LinkedList = require('../code-challenges/linked-list/insert-include-print.js');
+
+describe('finding the path between two numbers in a binary tree', () => {
+ it('should return a linked list representation of the path', () => {
+ let test = new BinaryTree(1);
+ test = test.root;
+ test.right = new BTnode(10);
+ test.right.right = new BTnode(4);
+ test.right.right.right = new BTnode(8);
+
+ test.left = new BTnode(15);
+ test.left.left = new BTnode(6);
+ test.left.left.left = new BTnode(7);
+
+ expect(findTreePath(test, 10, 8)).toBeInstanceOf(LinkedList);
+ });
+
+ it('should return null if the input is invalid', () => {
+ let test = new BinaryTree(1);
+
+ expect(findTreePath()).toBeNull();
+ expect(findTreePath(test)).toBeNull();
+ expect(findTreePath(test, 1)).toBeNull();
+ });
+
+ it('should return null if no path is found', () => {
+ let test = new BinaryTree(1);
+ test = test.root;
+ test.right = new BTnode(10);
+ test.right.right = new BTnode(4);
+ test.right.right.right = new BTnode(8);
+
+ test.left = new BTnode(15);
+ test.left.left = new BTnode(6);
+ test.left.left.left = new BTnode(7);
+ expect(findTreePath(test, 2, 500).head).toBeNull();
+ });
+});
+
+
+let test = new BinaryTree(1);
+test = test.root;
+test.right = new BTnode(10);
+test.right.right = new BTnode(4);
+test.right.right.right = new BTnode(8);
+
+test.left = new BTnode(15);
+test.left.left = new BTnode(6);
+test.left.left.left = new BTnode(7);
diff --git a/__tests__/flag-quicksort.test.js b/__tests__/flag-quicksort.test.js
new file mode 100644
index 0000000..6efda39
--- /dev/null
+++ b/__tests__/flag-quicksort.test.js
@@ -0,0 +1,14 @@
+'use strict';
+
+const flagQuicksort = require('../code-challenges/sorting/flag-quicksort');
+
+describe('using quicksort to create an el salvadorian flag', () => {
+ it('should create a flag', () => {
+ let flagArray = ['white','blue','blue', 'white', 'white', 'blue', 'white', 'white', 'white', 'shield', 'blue', 'blue', 'blue'];
+ const answer = undefined;
+ expect(flagQuicksort(flagArray)).toEqual(answer);
+ });
+ it('should return null if input is invalid', () => {
+ expect(flagQuicksort()).toBeNull();
+ });
+});
diff --git a/__tests__/graph.test.js b/__tests__/graph.test.js
new file mode 100644
index 0000000..2eda4aa
--- /dev/null
+++ b/__tests__/graph.test.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const Graph = require('../code-challenges/graph/graph.js');
+const Vertex = require('../code-challenges/graph/vertex.js');
+
+describe('graphs', () => {
+ it('should create a new graph', () => {
+ const test = new Graph();
+ expect(test).toBeInstanceOf(Graph);
+ });
+ it('should add new vertices', () => {
+ const test = new Graph();
+ test.addVertex(5);
+ expect(test._adjacencyList.has(5)).toBeTruthy();
+ });
+ it('should add new edges', () => {
+ const test = new Graph();
+ const vertex5 = new Vertex(5);
+ const vertex30 = new Vertex(30);
+
+ test.addVertex(vertex5);
+ test.addVertex(vertex30);
+ test.addEdge(vertex5, vertex30, 5);
+ expect(test._adjacencyList.get(vertex5).head.value.vertex.value).toEqual(30);
+ expect(test._adjacencyList.get(vertex5).head.value.weight).toEqual(5);
+ });
+ it('should add get a vertecies neighboring verticies', () => {
+ const test = new Graph();
+ const vertex5 = new Vertex(5);
+ const vertex30 = new Vertex(30);
+
+ test.addVertex(vertex5);
+ test.addVertex(vertex30);
+ test.addEdge(vertex5, vertex30, 5);
+ expect(test.getNeighbors(vertex5).value.vertex.value).toEqual(30);
+ });
+});
diff --git a/__tests__/hashTables.test.js b/__tests__/hashTables.test.js
new file mode 100644
index 0000000..7c3b38a
--- /dev/null
+++ b/__tests__/hashTables.test.js
@@ -0,0 +1,53 @@
+'use strict';
+
+/*
+
+Write tests to prove the following functionality:
+
+Adding a key/value to your hashtable results in the value being in the data structure
+Retrieving based on a key returns the value stored
+Successfully returns null for a key that does not exist in the hashtable
+Successfully handle a collision within the hashtable
+Successfully retrieve a value from a bucket within the hashtable that has a collision
+Successfully hash a key to an in-range value
+
+*/
+
+const HashTable = require('../code-challenges/hashtables/hashtables.js');
+
+describe('Hash Tables', () => {
+ it('should add a key/value', () => {
+ const test = new HashTable();
+ expect(test.add('key', 'value')).toEqual('value');
+ });
+
+ it('should return the value associated with the key', () => {
+ const test = new HashTable();
+ test.add('key', 'value');
+ expect(test.get('key')).toEqual('value');
+ });
+
+ it('successfully return null for a key that does not exist in the table', () => {
+ const test = new HashTable();
+ test.add('key', 'value');
+ expect(test.get('not a key')).toBeNull();
+ });
+
+ it('successfully handle a collision within the hashtable', () => {
+ const test = new HashTable();
+ test.add('key', 'value');
+ expect(test.data[61].nextkey = 'next value').toEqual('next value');
+ });
+
+ it('successfully retrieves a value from a bucket within the hashtable that has a collision', () => {
+ const test = new HashTable();
+ test.add('key', 'value');
+ test.data[61].nextkey = 'next value';
+ expect(test.get('key')).toEqual('value');
+ });
+
+ it('successfully hash a key to an in-range value', () => {
+ const test = new HashTable();
+ expect(test.hash('key')).toEqual(61);
+ });
+});
diff --git a/__tests__/leftjoin.test.js b/__tests__/leftjoin.test.js
new file mode 100644
index 0000000..96d0160
--- /dev/null
+++ b/__tests__/leftjoin.test.js
@@ -0,0 +1,41 @@
+'use strict';
+
+const leftJoin = require('../code-challenges/leftjoin/leftjoin.js');
+
+describe('left join', () => {
+ it('should join two hashmaps together', () => {
+ const test1 = new Map();
+ test1.set('k1', 'v1');
+ test1.set('k2', 'v2');
+ test1.set('k3', 'v3');
+
+ const test2 = new Map();
+ test2.set('k1', 'v21');
+ test2.set('k2', 'v22');
+ test2.set('k3', 'v23');
+
+ const answer = { k1: [ 'v1', 'v21' ], k2: [ 'v2', 'v22' ], k3: [ 'v3', 'v23' ] };
+ expect(leftJoin(test1,test2)).toEqual(answer);
+ });
+
+ it('should add a null to the new object if the value does not exist to be added', () => {
+ const test1 = new Map();
+ test1.set('k1', 'v1');
+ test1.set('k2', 'v2');
+ test1.set('k3', 'v3');
+
+ const test2 = new Map();
+ test2.set('k1', 'v21');
+ test2.set('k2', 'v22');
+
+ const answer = { k1: [ 'v1', 'v21' ], k2: [ 'v2', 'v22' ], k3: [ 'v3', null ] };
+ expect(leftJoin(test1,test2)).toEqual(answer);
+ });
+
+ it('should return null if the inputs are invalid', () => {
+ const test = new Map();
+
+ expect(leftJoin()).toBeNull;
+ expect(leftJoin(test)).toBeNull;
+ });
+});
diff --git a/__tests__/max-and-min-zeros.js b/__tests__/max-and-min-zeros.js
new file mode 100644
index 0000000..2ed1ae6
--- /dev/null
+++ b/__tests__/max-and-min-zeros.js
@@ -0,0 +1,25 @@
+'use strict';
+
+const findMaxAndMinZeros = require('../code-challenges/findMaxAndMinZeros/max-and-min-zeros.js');
+
+describe('find the rows with the most and least number of zeros given a 2d array', () => {
+ it('should find the max & min', () => {
+ const test = [
+ [0,0,0,1], //0
+ [0,0,0,1], //1
+ [0,0,1,1], //2
+ [0,0,0,1], //3
+ [0,0,0,0], //4
+ [0,0,0,1], //5
+ ];
+
+ const answer = findMaxAndMinZeros(test);
+ expect(answer.min).toEqual(4);
+ expect(answer.maxIdx).toEqual(2);
+ });
+
+ it('should return null if there is an invalid input', () => {
+ expect(findMaxAndMinZeros()).toBeNull();
+ expect(findMaxAndMinZeros([])).toBeNull();
+ });
+});
diff --git a/assets/chess.jpg b/assets/chess.jpg
new file mode 100644
index 0000000..c59af25
Binary files /dev/null and b/assets/chess.jpg differ
diff --git a/assets/dfs-graph.jpeg b/assets/dfs-graph.jpeg
new file mode 100644
index 0000000..dd1c701
Binary files /dev/null and b/assets/dfs-graph.jpeg differ
diff --git a/assets/findSumOfInts.jpg b/assets/findSumOfInts.jpg
new file mode 100644
index 0000000..037e4de
Binary files /dev/null and b/assets/findSumOfInts.jpg differ
diff --git a/assets/findTreeIntersection.jpg b/assets/findTreeIntersection.jpg
new file mode 100644
index 0000000..ef59111
Binary files /dev/null and b/assets/findTreeIntersection.jpg differ
diff --git a/assets/findTreePath.jpg b/assets/findTreePath.jpg
new file mode 100644
index 0000000..7470897
Binary files /dev/null and b/assets/findTreePath.jpg differ
diff --git a/assets/flag-quicksort.jpeg b/assets/flag-quicksort.jpeg
new file mode 100644
index 0000000..206becd
Binary files /dev/null and b/assets/flag-quicksort.jpeg differ
diff --git a/assets/leftjoin.jpg b/assets/leftjoin.jpg
new file mode 100644
index 0000000..0266f45
Binary files /dev/null and b/assets/leftjoin.jpg differ
diff --git a/assets/max-and-min-zeros.jpg b/assets/max-and-min-zeros.jpg
new file mode 100644
index 0000000..8c12643
Binary files /dev/null and b/assets/max-and-min-zeros.jpg differ
diff --git a/assets/more-array-reverse.jpg b/assets/more-array-reverse.jpg
new file mode 100644
index 0000000..35046e0
Binary files /dev/null and b/assets/more-array-reverse.jpg differ
diff --git a/code-challenges/array-reverse/array-reverse.js b/code-challenges/array-reverse/array-reverse.js
index e42dc16..08b6f0d 100644
--- a/code-challenges/array-reverse/array-reverse.js
+++ b/code-challenges/array-reverse/array-reverse.js
@@ -1,6 +1,8 @@
// Write a function called reverseArray which takes an array as an argument. Without utilizing any of the built-in methods available to your language, return an array with elements in reversed order.
function reverseArray(arr){
+ if(!arr) return null;
+ if(arr.length === 1) return arr;
let result = [];
for(let i = arr.length - 1; i >= 0; i--){
result.push(arr[i]);
@@ -8,12 +10,13 @@ function reverseArray(arr){
return result;
}
-console.log(reverseArray([1,2,3,4,5]));
// STRETCH GOAL
// Once you’ve achieved a working solution, implement the same feature with a different methodology. (Hint: what different techniques do you have when working with arrays? Recursion, loops, indexes, modifying the array input directly…)
function stretchGoal(arr){
+ if(!arr) return null;
+ if(arr.length === 1) return arr;
let result = [];
let length = arr.length;
for(let i = 0; i < length; i++){
@@ -23,4 +26,5 @@ function stretchGoal(arr){
return result;
}
-console.log(stretchGoal([1,2,3,4,5]));
+module.exports = {reverseArray, stretchGoal};
+
diff --git a/code-challenges/array-reverse/more-array-reverse.js b/code-challenges/array-reverse/more-array-reverse.js
new file mode 100644
index 0000000..c3d8ed6
--- /dev/null
+++ b/code-challenges/array-reverse/more-array-reverse.js
@@ -0,0 +1,17 @@
+'use strict';
+
+function reverseAnArray(array){
+ if(!array) return null;
+ if(array.length === 1) return array;
+ const middleOfArray = Math.floor(array.length / 2);
+ for(let i = 0; i < middleOfArray; i++){
+ let front = array[i];
+ let back = array[(array.length - 1) - i];
+
+ array[(array.length - 1) - i] = front;
+ array[i] = back;
+ }
+ return array;
+}
+
+module.exports = reverseAnArray;
diff --git a/code-challenges/chess/chess.js b/code-challenges/chess/chess.js
new file mode 100644
index 0000000..f30b6c0
--- /dev/null
+++ b/code-challenges/chess/chess.js
@@ -0,0 +1,49 @@
+'use strict';
+
+function _locatePieces(array){
+ const locations = new Map();
+ for(let i = 0; i < array.length; i++){
+ for(let j = 0; j < array.length; j++){
+ if(array[i][j] !== typeof 'number'){
+ locations.set(array[i][j], [i,j]);
+ }
+ }
+ }
+ return locations;
+}
+
+function _calculateRook(rookCoordinates, kingCoordinates){
+ const BOARD_DIMENSION = 8;
+ for(let i = 0; i < BOARD_DIMENSION; i++ ){
+ if(kingCoordinates === rookCoordinates){
+ return true;
+ }
+ rookCoordinates[0] += i;
+ }
+ return false;
+}
+
+function _calculateBishop(bishopCoordinates, kingCoordinates){
+ const BOARD_DIMENSION = 8;
+ for(let i = 0; i < BOARD_DIMENSION; i++){
+ if(kingCoordinates === bishopCoordinates){
+ return true;
+ }
+ bishopCoordinates[0] += i;
+ bishopCoordinates[1] += i;
+ }
+ return false;
+}
+
+function checkChessBoard(array){
+ const BOARD_DIMENSION = 8;
+ if(!array || array.length < BOARD_DIMENSION) return null;
+ const pieceLocations = _locatePieces(array);
+ const kingCoordinates = pieceLocations.get('k');
+ const bishopCoordinates = pieceLocations.get('b');
+ const rookCoordinates = pieceLocations.get('r');
+
+ return _calculateRook(rookCoordinates, kingCoordinates) && _calculateBishop(bishopCoordinates, kingCoordinates);
+}
+
+module.exports = checkChessBoard;
diff --git a/code-challenges/findMaxAndMinZeros/max-and-min-zeros.js b/code-challenges/findMaxAndMinZeros/max-and-min-zeros.js
new file mode 100644
index 0000000..1d3710f
--- /dev/null
+++ b/code-challenges/findMaxAndMinZeros/max-and-min-zeros.js
@@ -0,0 +1,42 @@
+'use strict';
+
+const _findPartition = array => {
+ let mid = Math.floor(array.length / 2);
+ for(let j = 0; j < array.length; j++){
+ if(array[mid] === 1){
+ if(array[mid - 1] === 0 || array[mid + 1] === 0){
+ return mid;
+ }
+ mid = Math.floor(mid / 2);
+ }
+ if(array[mid - 1] === 1 || array[mid + 1] === 1){
+ return mid;
+ }
+ mid = mid + Math.floor(mid / 2);
+ if(mid >= array.length) return 0;
+ }
+};
+
+const findMaxAndMinZeros = (array) => {
+ if(!array) return null;
+ if(array.length < 1) return null;
+ const result = {
+ max: 0,
+ maxIdx: 0,
+ min: 0,
+ minIdx: 0,
+ };
+ for(let i = 0; i < array.length; i++){
+ if(_findPartition(array[i]) > result.maxIdx){
+ result.maxIdx = _findPartition(array[i]);
+ result.max = i;
+ }
+ if(_findPartition(array[i]) <= result.minIdx){
+ result.minIdx = _findPartition(array[i]);
+ result.min = i;
+ }
+ }
+ return result;
+};
+
+module.exports = findMaxAndMinZeros;
diff --git a/code-challenges/findSumOfInts/findSumOfInts.js b/code-challenges/findSumOfInts/findSumOfInts.js
new file mode 100644
index 0000000..69e3970
--- /dev/null
+++ b/code-challenges/findSumOfInts/findSumOfInts.js
@@ -0,0 +1,24 @@
+'use strict';
+
+/*
+Problem Domain: Given an array of integers and a value, find a pair of integers in the array that add to that value.
+
+*/
+
+function findSumOfInts(array, key){
+ if(!array || !key) return null;
+ if(typeof key !== 'number' || typeof array !== 'object') return null;
+ if(array.length < 2) return null;
+ const hashMap = new Map();
+ for(let i = 0; i < array.length; i++){
+ hashMap.set(array[i]);
+ }
+ for(let j = 0; j < array.length; j++){
+ let difference = key - array[j];
+ if(hashMap.has(difference)){
+ return [array[j], difference];
+ }
+ }
+}
+
+module.exports = findSumOfInts;
diff --git a/code-challenges/findTreeIntersection/findTreeIntersection.js b/code-challenges/findTreeIntersection/findTreeIntersection.js
new file mode 100644
index 0000000..a6c1f85
--- /dev/null
+++ b/code-challenges/findTreeIntersection/findTreeIntersection.js
@@ -0,0 +1,53 @@
+'use strict';
+
+/**
+ * Returns a set contains the common values between two binary trees
+ *
+ * Complexity:
+ * Time: O(n)
+ * Space: O(n)
+ *
+ * @param {Binary Tree} treeOne
+ * @param {Binary Tree} treeTwo
+ * @returns {Set | null} : set containing common values between two binary trees
+ */
+module.exports = (treeOne, treeTwo) => {
+ if (!treeOne || !treeTwo || !treeOne.root || !treeTwo.root) return null;
+ const valueSet = treeAsSet(treeOne.root);
+ return commonValueSet(treeTwo.root, valueSet);
+};
+
+/**
+ * Recursive function that takes in a binary tree node and
+ * returns set containing all the unique values in a set.
+ *
+ * @param {Binary Tree Node} treeNode
+ * @param {Set | undefined} [set=new Set()]
+ * @returns {Set | null} : set of unique values in binary tree
+ */
+function treeAsSet(treeNode, set = new Set()) {
+ if (!treeNode) return null;
+ set.add(treeNode.value);
+ treeAsSet(treeNode.left, set);
+ treeAsSet(treeNode.right, set);
+ return set;
+}
+
+/**
+ * Recursive function that takes in a binary tree node, a set and
+ * returns a set of the common values between the tree and the set.
+ *
+ * @param {Binary Tree Node} treeNode
+ * @param {Set} valueSet
+ * @param {Set | undefined} [set=new Set()]
+ * @returns {Set | null} : set of common values
+ */
+function commonValueSet(treeNode, valueSet, set = new Set()) {
+ if (!treeNode) return null;
+ if (valueSet.has(treeNode.value)) {
+ set.add(treeNode.value);
+ }
+ commonValueSet(treeNode.left, valueSet, set);
+ commonValueSet(treeNode.right, valueSet, set);
+ return set;
+}
diff --git a/code-challenges/findTreePath/findTreePath.js b/code-challenges/findTreePath/findTreePath.js
new file mode 100644
index 0000000..98c2171
--- /dev/null
+++ b/code-challenges/findTreePath/findTreePath.js
@@ -0,0 +1,27 @@
+'use strict';
+const LinkedList = require('../linked-list/insert-include-print.js');
+
+function findTreePath(node, start, end, LLpath = new LinkedList(), foundStart = false, foundEnd = false){
+ if(!node || !start || !end) return null;
+ if(node){
+ if(node.value === start){
+ foundStart = true;
+ }
+ if(foundStart){
+ LLpath.insert(node.value);
+ if(node.value === end){
+ foundEnd = true;
+ return LLpath;
+ }
+ }
+ if(node.left){
+ findTreePath(node.left, start, end, LLpath, foundStart, foundEnd);
+ }
+ if(node.right){
+ findTreePath(node.right, start, end, LLpath, foundStart, foundEnd);
+ }
+ }
+ return LLpath;
+}
+
+module.exports = findTreePath;
diff --git a/code-challenges/graph/BFS.js b/code-challenges/graph/BFS.js
new file mode 100644
index 0000000..cf85593
--- /dev/null
+++ b/code-challenges/graph/BFS.js
@@ -0,0 +1,32 @@
+'use strict';
+const Queue = require('queue-fifo');
+
+module.exports = (graph, startVertex, goalVertex) => {
+ const queue = new Queue();
+ const visitedVertices = new Set();
+
+ const paths = new Map();
+
+ queue.enqueue(startVertex);
+ visitedVertices.add(startVertex);
+
+
+ while(queue.size() > 0) {
+ const currentVertex = queue.dequeue();
+
+ if(currentVertex === goalVertex) {
+ return paths;
+ }
+
+ let neighbor = graph.getNeighbors(currentVertex);
+ while(neighbor){
+ if(!visitedVertices.has(neighbor.value.vertex)){
+ visitedVertices.add(neighbor.value.vertex);
+ }
+ paths.set(neighbor.value.vertex, currentVertex);
+ queue.enqueue(neighbor.value.vertex);
+ neighbor = neighbor.next;
+ }
+ }
+ return null;
+};
diff --git a/code-challenges/graph/DFS.js b/code-challenges/graph/DFS.js
new file mode 100644
index 0000000..ae42b14
--- /dev/null
+++ b/code-challenges/graph/DFS.js
@@ -0,0 +1,32 @@
+'use strict';
+
+const Stack = require('stack-lifo');
+
+module.exports = (graph, startVertex, goalVertex) => {
+ const stack = new Stack();
+ const visitedVertices = new Set();
+
+ const paths = new Map();
+
+ stack.push(startVertex);
+ visitedVertices.add(startVertex);
+
+ while(stack.size() > 0) {
+ const currentVertex = stack.pop();
+
+ if(currentVertex === goalVertex) {
+ return paths;
+ }
+
+ let neighbor = graph.getNeighbors(currentVertex);
+ while(neighbor){
+ if(!visitedVertices.has(neighbor.value.vertex)){
+ visitedVertices.add(neighbor.value.vertex);
+ }
+ paths.set(neighbor.value.vertex, currentVertex);
+ stack.push(neighbor.value.vertex);
+ neighbor = neighbor.next;
+ }
+ }
+ return null;
+};
diff --git a/code-challenges/graph/README.md b/code-challenges/graph/README.md
new file mode 100644
index 0000000..3222355
--- /dev/null
+++ b/code-challenges/graph/README.md
@@ -0,0 +1,11 @@
+# Graph Implementation
+Given a graph with the adjacency list as an array, implement a linked list.
+Given BFS with an array as the data structure, implement a stack.
+Given DFS with an array as the data structure, implement a queue.
+
+## Efficiency
+BFS Time Complexity: O(n) where n is the number of verticies in the graph
+BFS Space Complexity: O(n) where n is the number of verticies in the graph
+
+DFS Time Complexity: O(n) where n is the number of verticies in the graph
+DFS Space Complexity: O(n) where n is the number of verticies in the graph
\ No newline at end of file
diff --git a/code-challenges/graph/dfs-challenge41.js b/code-challenges/graph/dfs-challenge41.js
new file mode 100644
index 0000000..9f79d6c
--- /dev/null
+++ b/code-challenges/graph/dfs-challenge41.js
@@ -0,0 +1,19 @@
+'use strict';
+
+function depthFirstTraversal(adjacenyList, visitedVerticies = new Set(), currentVertex = Object.keys(adjacenyList)[0]){
+ if(!visitedVerticies.has(currentVertex)){
+ visitedVerticies.add(currentVertex);
+ }
+ let neighbors = adjacenyList[currentVertex];
+ for(let neighbor of neighbors){
+ if(!visitedVerticies.has(neighbor)){
+ visitedVerticies.add(neighbor);
+ }else{
+ return visitedVerticies;
+ }
+ depthFirstTraversal(adjacenyList, visitedVerticies, neighbor);
+ }
+ return (visitedVerticies);
+}
+
+module.exports = depthFirstTraversal;
diff --git a/code-challenges/graph/dijkstra.js b/code-challenges/graph/dijkstra.js
new file mode 100644
index 0000000..9fe7da0
--- /dev/null
+++ b/code-challenges/graph/dijkstra.js
@@ -0,0 +1,65 @@
+'use strict';
+
+const PriorityQueue = require('js-priority-queue');
+
+module.exports = (graph, startVertex, goalVertex) => {
+
+ const priorityQueue = new PriorityQueue({
+ comparator: (a,b) => a.priority - b.priority,
+ });
+
+ const visitedVertices = new Set(); // Vinicio - this is still used, but we have to find out a different way
+ const paths = new Map();
+ const shortestPathSoFar = new Map();
+
+ priorityQueue.queue({
+ vertex: startVertex,
+ priority: 0, // Vinicio - this is the most important node right now
+ });
+
+ shortestPathSoFar.set(startVertex, 0);
+
+
+ while(priorityQueue.length > 0) {
+ const currentVertex = priorityQueue.dequeue().vertex;
+
+ // Many lines o this kind
+ if(visitedVertices.has(currentVertex)){
+ continue;
+ }
+
+ // Only one line of this kind
+ visitedVertices.add(currentVertex);
+
+ if(currentVertex === goalVertex) {
+ return paths;
+ }
+
+ // Dijkstra wants this code to execute to neighbors before we mark them as
+ // visited
+ const neighbors = graph.getNeighbors(currentVertex);
+
+ for(const neighbor of neighbors) {
+ const {weight, vertex: nextVertex} = neighbor;
+
+ if(visitedVertices.has(nextVertex)) {
+ continue;
+ }
+
+ const pathWeight = shortestPathSoFar.get(currentVertex) + weight;
+ // const pathWeight = shortestPathSoFar.get(currentVertex) + weight + heuristic(nextVertex);
+
+ if(!shortestPathSoFar.has(nextVertex) || pathWeight < shortestPathSoFar.get(nextVertex)) {
+ shortestPathSoFar.set(nextVertex, pathWeight);
+ paths.set(nextVertex, currentVertex);
+
+ priorityQueue.queue({
+ vertex: nextVertex,
+ priority: shortestPathSoFar.get(nextVertex),
+ });
+ }
+ }
+
+ }
+ return null;
+};
diff --git a/code-challenges/graph/graph.js b/code-challenges/graph/graph.js
new file mode 100644
index 0000000..f84320b
--- /dev/null
+++ b/code-challenges/graph/graph.js
@@ -0,0 +1,37 @@
+'use strict';
+
+const LinkedList = require('../linked-list/insert-include-print.js');
+
+module.exports = class Graph{
+ constructor(){
+ // Vinicio - adjacency list
+ this._adjacencyList = new Map();
+ }
+
+ addVertex(vertex) {
+ const LL = new LinkedList();
+ this._adjacencyList.set(vertex, LL);
+ }
+
+ // Vinicio - this edges are directed
+ addEdge(startVertex, endVertex, weight = 0) {
+ if(!this._adjacencyList.has(startVertex) ||
+ !this._adjacencyList.has(endVertex)) {
+ throw new Error('_INVALID_VERTEX_');
+ }
+
+ const edgeData = {
+ vertex: endVertex,
+ weight,
+ };
+
+ this._adjacencyList.get(startVertex).insert(edgeData);
+ }
+
+ getNeighbors(vertex){
+ if(!this._adjacencyList.has(vertex)){
+ throw new Error('_INVALID_VERTEX_');
+ }
+ return this._adjacencyList.get(vertex).head;
+ }
+};
diff --git a/code-challenges/graph/main.js b/code-challenges/graph/main.js
new file mode 100644
index 0000000..fe2e64e
--- /dev/null
+++ b/code-challenges/graph/main.js
@@ -0,0 +1,69 @@
+'use strict';
+const Graph = require('./graph.js');
+const Vertex = require('./vertex.js');
+const bfs = require('./BFS.js');
+const dfs = require('./DFS.js');
+const dijkstra = require('./dijkstra.js');
+
+const graph = new Graph();
+
+const vertex5 = new Vertex(5);
+const vertex10 = new Vertex(10);
+const vertex15 = new Vertex(15);
+const vertex20 = new Vertex(20);
+const vertex25 = new Vertex(25);
+const vertex30 = new Vertex(30);
+const vertex35 = new Vertex(35);
+const vertex40 = new Vertex(40);
+const vertex45 = new Vertex(45);
+const vertex50 = new Vertex(50);
+const vertex100 = new Vertex(100);
+
+graph.addVertex(vertex5);
+graph.addVertex(vertex10);
+graph.addVertex(vertex15);
+graph.addVertex(vertex20);
+graph.addVertex(vertex25);
+graph.addVertex(vertex30);
+graph.addVertex(vertex35);
+graph.addVertex(vertex40);
+graph.addVertex(vertex45);
+graph.addVertex(vertex50);
+graph.addVertex(vertex100);
+
+graph.addEdge(vertex5, vertex45);
+graph.addEdge(vertex5, vertex35);
+graph.addEdge(vertex5, vertex30, 5);
+graph.addEdge(vertex5, vertex20, 10);
+graph.addEdge(vertex5, vertex10, 1);
+
+
+graph.addEdge(vertex10, vertex20, 5);
+graph.addEdge(vertex10, vertex15, 1);
+
+graph.addEdge(vertex30, vertex40);
+graph.addEdge(vertex30, vertex20, 5);
+
+graph.addEdge(vertex40, vertex50);
+
+graph.addEdge(vertex20, vertex25, 10);
+graph.addEdge(vertex15, vertex25, 10000);
+
+let paths = bfs(graph, vertex5, vertex25);
+// console.log(paths);
+
+paths = dfs(graph, vertex5, vertex25);
+// console.log(paths);
+
+paths = dijkstra(graph,vertex5, vertex25);
+console.log(paths);
+
+
+// HW 1
+// Change arrays to linked lists in:
+// Graph class
+// BFS & DFS
+
+// HW 2
+// Modify Dijkstra to implement A*
+// Do not worry about finding the most optimal heuristic, just experiment
diff --git a/code-challenges/graph/vertex.js b/code-challenges/graph/vertex.js
new file mode 100644
index 0000000..cfa64b6
--- /dev/null
+++ b/code-challenges/graph/vertex.js
@@ -0,0 +1,7 @@
+'use strict';
+
+module.exports = class Vertex{
+ constructor(value) {
+ this.value = value;
+ }
+};
diff --git a/code-challenges/hashtables/hashtables.js b/code-challenges/hashtables/hashtables.js
new file mode 100644
index 0000000..eeedeac
--- /dev/null
+++ b/code-challenges/hashtables/hashtables.js
@@ -0,0 +1,56 @@
+'use strict';
+
+/*
+
+add: takes in both the key and value. This method should hash the key, and add the key and value pair to the table, handling collisions as needed.
+get: takes in the key and returns the value from the table.
+contains: takes in the key and returns a boolean, indicating if the key exists in the table already.
+hash: takes in an arbitrary key and returns an index in the collection.
+
+*/
+
+class HashTable{
+ constructor(length){
+ this.LENGTH = length || 100;
+ this.data = new Array(this.LENGTH);
+ for(let i = 0; i < this.LENGTH; i++){
+ this.data[i] = {};
+ }
+ }
+
+ _stringSum(key){
+ return key.split('').reduce((accumulator, current) => {
+ current = current.charCodeAt(0);
+ return accumulator += current;
+ },0);
+ }
+
+ hash(key){
+ if(typeof key !== 'string' && typeof key !== 'number') return null;
+
+ let convertedKey;
+ if(typeof key === 'string'){
+ convertedKey = this._stringSum(key);
+ }else{
+ convertedKey = key;
+ }
+ return convertedKey * 599 % (this.LENGTH - 1);
+ }
+
+ get(key){
+ let index = this.hash(key);
+ return this.data[index][key] ? this.data[index][key] : null;
+ }
+
+ contains(key){
+ let index = this.hash(key);
+ return !!this.data[index][key];
+ }
+
+ add(key, value){
+ const index = this.hash(key);
+ return Object.assign(this.data[index], {[key]: value})[key];
+ }
+}
+
+module.exports = HashTable;
diff --git a/code-challenges/leftjoin/leftjoin.js b/code-challenges/leftjoin/leftjoin.js
new file mode 100644
index 0000000..fce6c48
--- /dev/null
+++ b/code-challenges/leftjoin/leftjoin.js
@@ -0,0 +1,38 @@
+'use strict';
+
+/*
+
+* Write a function that LEFT JOINs two hashmaps into a single data structure.
+
+* The first parameter is a hashmap that has word strings as keys, and a synonym of the key as values.
+
+* The second parameter is a hashmap that has word strings as keys, and antonyms of the key as values.
+
+* Combine the key and corresponding values (if they exist) into a new data structure according to LEFT JOIN logic.
+
+LEFT JOIN means all the values in the first hashmap are returned, and if values exist in the “right” hashmap, they are appended to the result row.
+
+* If no values exist in the right hashmap, then some flavor of NULL should be appended to the result row.
+
+* The returned data structure that holds the results is up to you. It doesn’t need to exactly match the output below, so long as it achieves the LEFT JOIN logic.
+
+* Avoid utilizing any of the library methods available to your language.
+
+*/
+
+
+function leftJoin(map1, map2){
+ if(!map1 || !map2) return null;
+ let result = {};
+ map1.forEach((value, key) => {
+ result[key] = [value];
+ if(map2.has(key)){
+ result[key][result[key].length] = map2.get(key);
+ }else{
+ result[key][result[key].length] = null;
+ }
+ });
+ return result;
+}
+
+module.exports = leftJoin;
diff --git a/code-challenges/linked-list/node.js b/code-challenges/linked-list/node.js
index fb6dc8d..e26a938 100644
--- a/code-challenges/linked-list/node.js
+++ b/code-challenges/linked-list/node.js
@@ -1,6 +1,5 @@
'use strict';
-
class Node {
constructor(){
this.value = null;
diff --git a/code-challenges/sorting/3way-quicksort.js b/code-challenges/sorting/3way-quicksort.js
new file mode 100644
index 0000000..a779d0b
--- /dev/null
+++ b/code-challenges/sorting/3way-quicksort.js
@@ -0,0 +1,59 @@
+'use strict';
+
+// Improve our quicksort implementation to use "three-way partition". Document your process
+
+const _swap = (array, indexA, indexB) => {
+ const helper = array[indexA];
+ array[indexA] = array[indexB];
+ array[indexB] = helper;
+};
+
+const _sort3way = (array, leftSide, rightSide) => {
+ if (leftSide < rightSide) {
+ let lastLowIndex = leftSide;
+ let firstHighIndex = rightSide;
+ const pivotIndex = array[leftSide];
+
+ let i = leftSide;
+
+ while (i <= firstHighIndex) {
+ if (array[i] < pivotIndex) {
+ _swap(array, i, lastLowIndex);
+ i++;
+ lastLowIndex++;
+ } else if (array[i] > pivotIndex) {
+ _swap(array, i, firstHighIndex);
+ firstHighIndex--;
+ } else {
+ i++;
+ }
+ }
+
+ _sort3way(array, leftSide, lastLowIndex - 1);
+ _sort3way(array, firstHighIndex + 1, rightSide);
+ }
+};
+
+const quicksort = (array) => {
+ _sort3way(array, 0, array.length - 1);
+};
+
+let array = [4,5,3,1];
+quicksort(array);
+console.log(array);
+
+array = [1, 2];
+quicksort(array);
+console.log(array);
+
+array = [2, 1,3,6,4,9,8,7,6];
+quicksort(array);
+console.log(array);
+
+array = [2,1,3,6,4,9,8,7,6,3,6,9,2,6,0,4,2,6,3,7];
+quicksort(array);
+console.log(array);
+
+array = [2,1,3,6,4,9,8,7,6,3,6,9,2,6,0,4,2,6,3,7];
+quicksort(array);
+console.log(array);
diff --git a/code-challenges/sorting/demo-mergesort.js b/code-challenges/sorting/demo-mergesort.js
new file mode 100644
index 0000000..cc77f87
--- /dev/null
+++ b/code-challenges/sorting/demo-mergesort.js
@@ -0,0 +1,56 @@
+'use strict';
+
+//Improve the performance of our merge sort implementation. Document your process
+
+/**
+ * This method assumes sorting in ascending order
+ */
+const mergeSort = items => {
+ // --------------------------------------------------------------
+ // BASE CASES
+ // --------------------------------------------------------------
+ if (items.length < 2) {
+ return items; // Vinicio - already sorted
+ }
+
+ if (items.length === 2) {
+ return items[0] < items[1] ? items : items.reverse();
+ }
+ // --------------------------------------------------------------
+ // RECURSIVE CASES
+ // --------------------------------------------------------------
+ const middlePoint = Math.floor(items.length / 2);
+
+ // Vinicio - going down in the recursive tree
+ const leftSide = mergeSort(items.slice(0, middlePoint));
+ const rightSide = mergeSort(items.slice(middlePoint));
+
+ // Vinicio - here we assume that left and right have been pre-sorted
+ let output = [];
+ while(leftSide.length > 0 && rightSide.length > 0) {
+ if(leftSide[0] <= rightSide[0]) {
+ output.push(leftSide[0]);
+ leftSide.shift();
+ }
+ else {
+ output.push(rightSide[0]);
+ rightSide.shift();
+ }
+ }
+ // Vinicio - if we are here, one of the arrays must be empty
+ if(leftSide.length === 0 && rightSide.length > 0) {
+ // Vinicio - we only have values on the right side
+ output = output.concat(rightSide); // Vinicio - we might need to find a way to optimize this
+ }
+ if(rightSide.length === 0 && leftSide.length > 0) {
+ // Vinicio - we only have values on the left side
+ output = output.concat(leftSide);
+ }
+ return output;
+};
+
+
+console.log(mergeSort([1]));
+console.log(mergeSort([1, 2]));
+console.log(mergeSort([2, 1,3,6,4,9,8,7,6]));
+
diff --git a/code-challenges/sorting/demo-quicksort.js b/code-challenges/sorting/demo-quicksort.js
new file mode 100644
index 0000000..c6cfa5b
--- /dev/null
+++ b/code-challenges/sorting/demo-quicksort.js
@@ -0,0 +1,58 @@
+'use strict';
+
+// Improve our quicksort implementation to use "three-way partition". Document your process
+
+const _swap = (items, indexA, indexB) => {
+ const helper = items[indexA];
+
+ items[indexA] = items[indexB];
+ items[indexB] = helper;
+};
+
+const _partition = (items, leftIndex, rightIndex) => {
+ const pivotIndex = rightIndex; // findPivot(items, leftIndex, rightIndex);
+ let firstHighIndex = leftIndex;
+
+ for(let i = leftIndex; i < rightIndex; i ++){
+ if(items[i] < items[pivotIndex]) {
+ _swap(items, i, firstHighIndex);
+ firstHighIndex++;
+ }
+ }
+ _swap(items, pivotIndex, firstHighIndex);
+ return firstHighIndex; // Vinicio - this becomes the pivot's index
+};
+
+const _helper = (items, leftIndex, rightIndex) => {
+
+ // if(rightIndex - leftIndex <= 10) {
+ // insertionSort(items);
+ // }
+ if (rightIndex > leftIndex) {
+ const partitionIndex = _partition(items, leftIndex, rightIndex);
+
+ _helper(items,leftIndex, partitionIndex -1);
+ _helper(items, partitionIndex + 1, rightIndex);
+ }
+};
+
+const quicksort = items => {
+ return _helper(items, 0, items.length -1);
+};
+
+
+let array = [4,5,3,1];
+quicksort(array);
+console.log(array);
+
+array = [1, 2];
+quicksort(array);
+console.log(array);
+
+array = [2, 1,3,6,4,9,8,7,6];
+quicksort(array);
+console.log(array);
+
+array = [2,1,3,6,4,9,8,7,6,3,6,9,2,6,0,4,2,6,3,7];
+quicksort(array);
+console.log(array);
diff --git a/code-challenges/sorting/efficient-mergesort.js b/code-challenges/sorting/efficient-mergesort.js
new file mode 100644
index 0000000..44cbed9
--- /dev/null
+++ b/code-challenges/sorting/efficient-mergesort.js
@@ -0,0 +1,26 @@
+'use strict';
+
+//Improve the performance of our merge sort implementation. Document your process
+
+const _merge = (leftSide, rightSide) => {
+ let result = [];
+ while(leftSide.length > 0 && rightSide > 0){
+ result.push(leftSide[0] < rightSide[0] ? leftSide.shift() : rightSide.shift());
+ }
+ return result.concat(leftSide.length ? leftSide : rightSide);
+};
+
+const mergeSort = array => {
+ if(array.length < 2) return array;
+ let mid = Math.floor(array.length / 2);
+ let leftSide = array.slice(0,mid);
+ let rightSide = array.slice(mid);
+
+ return _merge(mergeSort(leftSide), mergeSort(rightSide));
+};
+
+
+console.log(mergeSort([1]));
+console.log(mergeSort([1, 2]));
+console.log(mergeSort([2,1,3,6,4,9,8,7,6]));
+
diff --git a/code-challenges/sorting/flag-quicksort.js b/code-challenges/sorting/flag-quicksort.js
new file mode 100644
index 0000000..a4d4559
--- /dev/null
+++ b/code-challenges/sorting/flag-quicksort.js
@@ -0,0 +1,84 @@
+/* eslint-disable no-fallthrough */
+'use strict';
+
+const makeFlag = array => {
+ if(!array) return null;
+ let center = Math.floor((array.length - 1) / 2);
+ let b = 0;
+ let w = 0;
+ let firstBlue;
+ let lastBlue;
+ let firstWhite;
+ let lastWhite;
+
+ const _swap = (items, indexA, indexB) => {
+ const helper = items[indexA];
+
+ items[indexA] = items[indexB];
+ items[indexB] = helper;
+ };
+
+ const _partition = (items, leftIndex, rightIndex) => {
+ const pivotIndex = rightIndex;
+ let firstHighIndex = leftIndex;
+
+
+ switch(items[leftIndex]) {
+ case 'shield':
+ if(leftIndex === center) {
+ return;
+ }
+ else {
+ _swap(array, leftIndex, center);
+ }
+ case 'blue':
+ b++;
+ if (b < 2) {
+ firstBlue = leftIndex;
+ if(leftIndex > b) {
+ _swap(array, leftIndex, firstBlue);
+ }
+ }
+ else {
+ lastBlue = leftIndex;
+ if(leftIndex < b) {
+ _swap(array, leftIndex, lastBlue);
+ }
+ }
+ case 'white':
+ w++;
+ if (w < 4 && w > 2) {
+ firstWhite = leftIndex;
+ if(leftIndex > w) {
+ _swap(array, leftIndex, firstWhite);
+ }
+ }
+ else {
+ lastWhite = leftIndex;
+ if(leftIndex < w) {
+ _swap(array, leftIndex, lastWhite);
+ }
+ }
+ default:
+ _swap(items, pivotIndex, firstHighIndex);
+ }
+
+ return firstHighIndex;
+ };
+
+ const _helper = (items, leftIndex, rightIndex) => {
+
+ if (rightIndex > leftIndex) {
+ const partitionIndex = _partition(items, leftIndex, rightIndex);
+
+ _helper(items,leftIndex, partitionIndex -1);
+ _helper(items, partitionIndex + 1, rightIndex);
+ }
+ };
+ const sort = items => {
+ return _helper(items, 0, items.length -1);
+ };
+ sort(array);
+};
+
+module.exports = makeFlag;
diff --git a/package-lock.json b/package-lock.json
index ca871a6..fa85ee4 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1003,6 +1003,14 @@
}
}
},
+ "dbly-linked-list": {
+ "version": "0.3.4",
+ "resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.3.4.tgz",
+ "integrity": "sha512-327vOlwspi9i1T3Kc9yZhRUR8qDdgMQ4HmXsFDDCQ/HTc3sNe7gnF5b0UrsnaOJ0rvmG7yBZpK0NoOux9rKYKw==",
+ "requires": {
+ "lodash.isequal": "^4.5.0"
+ }
+ },
"debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -3019,6 +3027,11 @@
}
}
},
+ "js-priority-queue": {
+ "version": "0.1.5",
+ "resolved": "https://registry.npmjs.org/js-priority-queue/-/js-priority-queue-0.1.5.tgz",
+ "integrity": "sha1-9x6bISDJHood2rO300fawB2B6Dc="
+ },
"js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -3182,6 +3195,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
+ "lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA="
+ },
"lodash.sortby": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
@@ -3784,6 +3802,14 @@
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
},
+ "queue-fifo": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/queue-fifo/-/queue-fifo-0.2.6.tgz",
+ "integrity": "sha512-rwlnZHAaTmWEGKC7ziasK8u4QnZW/uN6kSiG+tHNf/1GA+R32FArZi18s3SYUpKcA0Y6jJoUDn5GT3Anoc2mWw==",
+ "requires": {
+ "dbly-linked-list": "0.3.4"
+ }
+ },
"react-is": {
"version": "16.8.6",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz",
@@ -4302,6 +4328,24 @@
"tweetnacl": "~0.14.0"
}
},
+ "stack-lifo": {
+ "version": "0.1.6",
+ "resolved": "https://registry.npmjs.org/stack-lifo/-/stack-lifo-0.1.6.tgz",
+ "integrity": "sha512-fNXXK6AHbOIExOtJYPb1RlP8OXQr8tlpDNP5I78ZId9uK+MDCcDAkwGWTDACYLXAwOhaKLTYwkoSOihAt+/cLg==",
+ "requires": {
+ "dbly-linked-list": "0.2.0"
+ },
+ "dependencies": {
+ "dbly-linked-list": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dbly-linked-list/-/dbly-linked-list-0.2.0.tgz",
+ "integrity": "sha512-Ool7y15f6JRDs0YKx7Dh9uiTb1jS1SZLNdT3Y2q16DlaEghXbMsmODS/XittjR2xztt1gJUpz7jVxpqAPF8VGg==",
+ "requires": {
+ "lodash.isequal": "^4.5.0"
+ }
+ }
+ }
+ },
"stack-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-1.0.2.tgz",
diff --git a/package.json b/package.json
index ed45dec..1c20edf 100644
--- a/package.json
+++ b/package.json
@@ -12,6 +12,9 @@
"license": "MIT",
"dependencies": {
"eslint": "^5.16.0",
- "jest": "^24.1.0"
+ "jest": "^24.1.0",
+ "js-priority-queue": "^0.1.5",
+ "queue-fifo": "^0.2.6",
+ "stack-lifo": "^0.1.6"
}
}