From 62c035f5a573d7e7a7fb9e628660d27f6cdc737d Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 30 Jan 2018 18:31:40 -0800 Subject: [PATCH 01/13] Caroline Cariste: Tree tests passing, starting BST --- package.json | 2 ++ src/binary-search-tree.js | 34 ++++++++++++++++++++++++++++++++-- src/tree.js | 18 +++++++++++++++--- 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 60e89dc..3c19e50 100644 --- a/package.json +++ b/package.json @@ -4,6 +4,8 @@ "description": "LambdaSchool's Data Structures II", "main": "index.js", "scripts": { + "test:nolint": "jest --verbose", + "mytest": "npm run test:nolint -- --watch", "test": "eslint tests/*.js && eslint src/*.js && jest --verbose", "lint": "eslint", "test:watch": "npm test -- --watch" diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 262a838..96303c4 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -12,7 +12,31 @@ class BinarySearchTree { // assigns it to either the left or right subtree, // depending on its value insert(value) { - + if (this.value === null) { + let bst = new BinarySearchTree(value); + console.log('new', value); + return; + } + if (value > this.value) { + console.log('greater than', value); + if (!this.right) { + this.right = value; + console.log('this.right', value); + return; + } + let right = this.right; + console.log(right.insert(value)); + right.insert(value); + } + if (value <= this.value) { + if (!this.left) { + this.left = value; + return; + } + let left = this.left; + console.log(left.insert(value)); + left.insert(value); + } } // Checks the binary search tree for the input target // Can be written recursively or iteratively @@ -24,7 +48,7 @@ class BinarySearchTree { depthFirstForEach(cb) { } - // Traverses the tree in a breadth-first manner, i.e. in layers, starting + // Traverses the tree in a breadth-first manner, i.e. in layers, starting // at the root node, going down to the root node's children, and iterating // through all those nodes first before moving on to the next layer of nodes // Applies the given callback to each tree node in the process @@ -35,4 +59,10 @@ class BinarySearchTree { } } +let binarySearchTree = new BinarySearchTree(5); +binarySearchTree.insert(2); +binarySearchTree.insert(3); +binarySearchTree.insert(7); +binarySearchTree.insert(6); + module.exports = BinarySearchTree; diff --git a/src/tree.js b/src/tree.js index b6b7908..23e4a35 100644 --- a/src/tree.js +++ b/src/tree.js @@ -5,15 +5,27 @@ class Tree { this.value = value; this.children = []; } - // Adds a new Tree node with the input value to the current Tree node + // Adds a new Tree node with the input value to the current Tree node addChild(value) { - + let newChild = new Tree; + newChild.value = value; + this.children.push(newChild); } // Checks this node's children to see if any of them matches the given value // Continues recursively until the value has been found or all of the children // have been checked contains(value) { - + if (this.value === value) { + return true; + } + if (this.children) { + let result = false; + for (let i = 0; result === false && i < this.children.length; i++) { + result = this.children[i].contains(value); + } + return result; + } + return false; } } From 63c71a8b5709cebea1a3bd4d0f96719ece671c09 Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 30 Jan 2018 19:46:32 -0800 Subject: [PATCH 02/13] Caroline Cariste: Passing BST insert and contains, DF For Each in progress --- src/binary-search-tree.js | 44 +++++++++++++++++++++++++++------------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 96303c4..712be64 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -14,38 +14,56 @@ class BinarySearchTree { insert(value) { if (this.value === null) { let bst = new BinarySearchTree(value); - console.log('new', value); return; } if (value > this.value) { - console.log('greater than', value); if (!this.right) { - this.right = value; - console.log('this.right', value); + this.right = new BinarySearchTree(value); return; } - let right = this.right; - console.log(right.insert(value)); - right.insert(value); - } + return this.right.insert(value); + } if (value <= this.value) { if (!this.left) { - this.left = value; + this.left = new BinarySearchTree(value); return; } - let left = this.left; - console.log(left.insert(value)); - left.insert(value); + return this.left.insert(value); } } + // Checks the binary search tree for the input target // Can be written recursively or iteratively contains(target) { - + if (this.value === target) { + return true; + } + if (this.value === null) { + return false; + } + if (target > this.value && this.right !== null) { + return this.right.contains(target); + } + if (target <= this.value && this.left !== null) { + return this.left.contains(target); + } + return false; } // Traverses the tree in a depth-first manner, i.e. from top to bottom // Applies the given callback to each tree node in the process depthFirstForEach(cb) { + if (this.value === null) { return; } + cb(this.value); + if (this.left.value) { + cb(this.left); + return this.left.depthFirstForEach(cb); + } + if (this.right) { + cb(this.right.value); + return this.right.depthFirstForEach(cb); + } + if (this.right === null && this.left === null) { return; } + } // Traverses the tree in a breadth-first manner, i.e. in layers, starting From fcdc90d65f376d092c2cc57c7f4b613baa499a41 Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 30 Jan 2018 19:59:27 -0800 Subject: [PATCH 03/13] CRC: DFS for Each Passing, Beginning BFS for Each on BST --- src/binary-search-tree.js | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 712be64..302e269 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -54,17 +54,13 @@ class BinarySearchTree { depthFirstForEach(cb) { if (this.value === null) { return; } cb(this.value); - if (this.left.value) { - cb(this.left); - return this.left.depthFirstForEach(cb); + if (this.left) { + this.left.depthFirstForEach(cb); } if (this.right) { - cb(this.right.value); - return this.right.depthFirstForEach(cb); + this.right.depthFirstForEach(cb); } if (this.right === null && this.left === null) { return; } - - } // Traverses the tree in a breadth-first manner, i.e. in layers, starting // at the root node, going down to the root node's children, and iterating @@ -73,7 +69,15 @@ class BinarySearchTree { // You'll need the queue-helper file for this. Or could you roll your own queue // again. Whatever floats your boat. breadthFirstForEach(cb) { - + if (this.value === null) { return; } + cb(this.value); + if (this.left) { + this.left.depthFirstForEach(cb); + } + if (this.right) { + this.right.depthFirstForEach(cb); + } + if (this.right === null && this.left === null) { return; } } } From bcb2734c927ad747111a0450c6451f825ff34c96 Mon Sep 17 00:00:00 2001 From: Charlie Date: Tue, 30 Jan 2018 23:08:58 -0800 Subject: [PATCH 04/13] CRC: still working through BF For Each --- src/binary-search-tree.js | 49 +++++++++++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 10 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 302e269..5daac1b 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -2,6 +2,24 @@ /* eslint-disable global-require */ /* eslint-disable no-unused-vars */ /* eslint-disable no-trailing-spaces */ +class Queue { + constructor() { + this.storage = []; + } + + enqueue(x) { + this.storage.push(x); + } + + dequeue() { + return this.storage.shift(); + } + + isEmpty() { + return this.storage.length === 0; + } +} + class BinarySearchTree { constructor(value) { this.value = value; @@ -69,22 +87,33 @@ class BinarySearchTree { // You'll need the queue-helper file for this. Or could you roll your own queue // again. Whatever floats your boat. breadthFirstForEach(cb) { + let q = new Queue; if (this.value === null) { return; } - cb(this.value); - if (this.left) { - this.left.depthFirstForEach(cb); - } - if (this.right) { - this.right.depthFirstForEach(cb); + q.enqueue(this.value); + console.log(q); + let currentNode = this; + console.log(currentNode) + while (currentNode !== null) { + if (currentNode.left) { + q.enqueue(this.left.value); + } + if (currentNode.right) { + q.enqueue(this.right.value); + } + cb(q.dequeue()); + currentNode = q.dequeue(); } - if (this.right === null && this.left === null) { return; } } } let binarySearchTree = new BinarySearchTree(5); -binarySearchTree.insert(2); +const array = []; +const foo = value => ((array.push(value))); binarySearchTree.insert(3); -binarySearchTree.insert(7); -binarySearchTree.insert(6); +binarySearchTree.insert(4); +binarySearchTree.insert(10); +binarySearchTree.insert(9); +binarySearchTree.insert(11); +binarySearchTree.breadthFirstForEach(foo); module.exports = BinarySearchTree; From a9fcf0de02b9d540f765802c6dd21c99abed550e Mon Sep 17 00:00:00 2001 From: Charlie Date: Wed, 31 Jan 2018 13:25:43 -0800 Subject: [PATCH 05/13] CRC: BFS Passes - Phew --- src/binary-search-tree.js | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 5daac1b..75e5b27 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -89,31 +89,19 @@ class BinarySearchTree { breadthFirstForEach(cb) { let q = new Queue; if (this.value === null) { return; } - q.enqueue(this.value); - console.log(q); + q.enqueue(this); let currentNode = this; - console.log(currentNode) - while (currentNode !== null) { + while (!q.isEmpty()) { + currentNode = q.dequeue(); if (currentNode.left) { - q.enqueue(this.left.value); + q.enqueue(currentNode.left); } if (currentNode.right) { - q.enqueue(this.right.value); + q.enqueue(currentNode.right); } - cb(q.dequeue()); - currentNode = q.dequeue(); + cb(currentNode.value); } } } -let binarySearchTree = new BinarySearchTree(5); -const array = []; -const foo = value => ((array.push(value))); -binarySearchTree.insert(3); -binarySearchTree.insert(4); -binarySearchTree.insert(10); -binarySearchTree.insert(9); -binarySearchTree.insert(11); -binarySearchTree.breadthFirstForEach(foo); - module.exports = BinarySearchTree; From d0f288a7f7c59ab971de5a8d9bf8c2136a2662d1 Mon Sep 17 00:00:00 2001 From: Charlie Date: Wed, 31 Jan 2018 18:55:56 -0800 Subject: [PATCH 06/13] CRC: added require to allow Queue helper file usage. Started graphs, addVertex and contains methods passing --- src/binary-search-tree.js | 28 ++++------------------------ src/graph.js | 24 +++++++++++++++++------- 2 files changed, 21 insertions(+), 31 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 75e5b27..4f1e968 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -2,23 +2,7 @@ /* eslint-disable global-require */ /* eslint-disable no-unused-vars */ /* eslint-disable no-trailing-spaces */ -class Queue { - constructor() { - this.storage = []; - } - - enqueue(x) { - this.storage.push(x); - } - - dequeue() { - return this.storage.shift(); - } - - isEmpty() { - return this.storage.length === 0; - } -} +const Queue = require('./queue-helper'); class BinarySearchTree { constructor(value) { @@ -31,7 +15,7 @@ class BinarySearchTree { // depending on its value insert(value) { if (this.value === null) { - let bst = new BinarySearchTree(value); + this.value = new BinarySearchTree(value); return; } if (value > this.value) { @@ -53,12 +37,8 @@ class BinarySearchTree { // Checks the binary search tree for the input target // Can be written recursively or iteratively contains(target) { - if (this.value === target) { - return true; - } - if (this.value === null) { - return false; - } + if (this.value === target) return true; + if (this.value === null) return false; if (target > this.value && this.right !== null) { return this.right.contains(target); } diff --git a/src/graph.js b/src/graph.js index 80eeb07..c9ea6d5 100644 --- a/src/graph.js +++ b/src/graph.js @@ -35,19 +35,30 @@ class Graph { this.vertices = []; } // Wraps the input value in a new GraphNode and adds it to the array of vertices - // If there are only two nodes in the graph, they need to be automatically + // If there are only two nodes in the graph, they need to be automatically // connected via an edge // Optionally accepts an array of other GraphNodes for the new vertex to be connected to // Returns the newly-added vertex addVertex(value, edges = []) { - + let ngn = new GraphNode({ value, edges }); + console.log(ngn); + if (this.vertices.length === 2) { + this.vertices[0].edges = ngn; + ngn.edges = this.vertices[0]; + } + this.vertices.push(ngn); + console.log(this.vertices); + return ngn; } // Checks all the vertices of the graph for the target value // Returns true or false contains(value) { - + for (let i = 0; i < this.vertices.length; i++) { + if (this.vertices[i].value === value) return true; + } + return false; } - // Checks the graph to see if a GraphNode with the specified value exists in the graph + // Checks the graph to see if a GraphNode with the specified value exists in the graph // and removes the vertex if it is found // This function should also handle the removing of all edge references for the removed vertex removeVertex(value) { @@ -56,13 +67,13 @@ class Graph { // Checks the two input vertices to see if each one references the other in their respective edges array // Both vertices must reference each other for the edge to be considered valid // If only one vertex references the other but not vice versa, should not return true - // Note: You'll need to store references to each vertex's array of edges so that you can use + // Note: You'll need to store references to each vertex's array of edges so that you can use // array methods on said arrays. There is no method to traverse the edge arrays built into the GraphNode class checkIfEdgeExists(fromVertex, toVertex) { } // Adds an edge between the two given vertices if no edge already exists between them - // Again, an edge means both vertices reference the other + // Again, an edge means both vertices reference the other addEdge(fromVertex, toVertex) { } @@ -76,4 +87,3 @@ class Graph { } module.exports = Graph; - From 6bd1205a00842c5d2a0dfed100e9480e87256cea Mon Sep 17 00:00:00 2001 From: Charlie Date: Wed, 31 Jan 2018 20:51:26 -0800 Subject: [PATCH 07/13] CRC: graphs can add node, automatically create edges for a two node graph, and I think contains and checkIfEdgeExists works --- src/graph.js | 60 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/src/graph.js b/src/graph.js index c9ea6d5..3ce244a 100644 --- a/src/graph.js +++ b/src/graph.js @@ -41,15 +41,15 @@ class Graph { // Returns the newly-added vertex addVertex(value, edges = []) { let ngn = new GraphNode({ value, edges }); - console.log(ngn); + this.vertices.push(ngn); if (this.vertices.length === 2) { - this.vertices[0].edges = ngn; - ngn.edges = this.vertices[0]; + this.vertices[0].pushToEdges(ngn); + this.vertices[1].pushToEdges(this.vertices[0]); } - this.vertices.push(ngn); - console.log(this.vertices); + console.log('vertices are now', this.vertices); return ngn; } + // Checks all the vertices of the graph for the target value // Returns true or false contains(value) { @@ -62,28 +62,70 @@ class Graph { // and removes the vertex if it is found // This function should also handle the removing of all edge references for the removed vertex removeVertex(value) { - + let removed; + if (!this.contains(value)) return; + if (this.contains(value)) { + for (let i = 0; i < this.vertices.length; i++) { + if (this.vertices[i].value === value) { + removed = this.vertices[i]; + let newVertices = this.vertices.slice(i, 1); + console.log(newVertices); + console.log(removed.edges); + if (removed.edges) { + for (edge in removed.edges) { + removeEdge(removed, edge); + } + } + } + } } +} // Checks the two input vertices to see if each one references the other in their respective edges array // Both vertices must reference each other for the edge to be considered valid // If only one vertex references the other but not vice versa, should not return true // Note: You'll need to store references to each vertex's array of edges so that you can use // array methods on said arrays. There is no method to traverse the edge arrays built into the GraphNode class checkIfEdgeExists(fromVertex, toVertex) { - + if (fromVertex.edges.indexOf(toVertex) === -1 || toVertex.edges.indexOf(fromVertex) === -1) { + console.log('check edge', fromVertex, toVertex, false); + return false; + } + console.log('check edge', fromVertex, toVertex, true); + return true; } // Adds an edge between the two given vertices if no edge already exists between them // Again, an edge means both vertices reference the other addEdge(fromVertex, toVertex) { - + if (!this.checkIfEdgeExists(fromVertex, toVertex)) { + console.log('edge does not exist'); + fromVertex.pushToEdges(toVertex); + toVertex.pushToEdges(fromVertex); + } } // Removes the edge between the two given vertices if an edge already exists between them // After removing the edge, neither vertex should be referencing the other // If a vertex would be left without any edges as a result of calling this function, those // vertices should be removed as well removeEdge(fromVertex, toVertex) { - + let index = fromVertex.edges.indexOf(toVertex); } } +// let graph = new Graph(); +// graph.addVertex('Hello World!'); +// graph.addVertex('hi there'); +// // graph.removeVertex('hi there'); +// const pineapple = graph.addVertex('pineapple'); +// const banana = graph.addVertex('banana'); +// const mango = graph.addVertex('mango', [pineapple]); +// const monkey = graph.addVertex('monkey'); +// const human = graph.addVertex('human'); +// const crocodile = graph.addVertex('crocodile', [human]); +// graph.addEdge(crocodile, monkey); +// graph.removeEdge(monkey, human); +// graph.checkIfEdgeExists(crocodile, monkey); +// const A = graph.addVertex('A'); +// const b = graph.addVertex('b'); +// graph.removeEdge(A, b); + module.exports = Graph; From 4a1feb756ac50b3e066167c0896cb4c95c377481 Mon Sep 17 00:00:00 2001 From: Charlie Date: Wed, 31 Jan 2018 21:56:44 -0800 Subject: [PATCH 08/13] CRC: graph add edge method completed, passes manual tests, but not suite tests --- src/graph.js | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/graph.js b/src/graph.js index 3ce244a..d7d8eb7 100644 --- a/src/graph.js +++ b/src/graph.js @@ -96,34 +96,47 @@ class Graph { // Adds an edge between the two given vertices if no edge already exists between them // Again, an edge means both vertices reference the other addEdge(fromVertex, toVertex) { - if (!this.checkIfEdgeExists(fromVertex, toVertex)) { - console.log('edge does not exist'); - fromVertex.pushToEdges(toVertex); - toVertex.pushToEdges(fromVertex); - } + if (this.checkIfEdgeExists(fromVertex, toVertex)) return; + fromVertex.pushToEdges(toVertex); + toVertex.pushToEdges(fromVertex); } // Removes the edge between the two given vertices if an edge already exists between them // After removing the edge, neither vertex should be referencing the other // If a vertex would be left without any edges as a result of calling this function, those // vertices should be removed as well removeEdge(fromVertex, toVertex) { - let index = fromVertex.edges.indexOf(toVertex); + if (this.checkIfEdgeExists(fromVertex, toVertex)) { + console.log('edge exists'); + let fromIndex = fromVertex.edges.indexOf(toVertex); + fromVertex.edges.splice(fromIndex, 1); + let toIndex = toVertex.edges.indexOf(fromVertex); + toVertex.edges.splice(toIndex, 1); + } + if (!fromVertex.edges) { + this.removeEdge(fromVertex); + } + if (!toVertex.edges) { + this.removeEdge(toVertex); + } } } -// let graph = new Graph(); +let graph = new Graph(); // graph.addVertex('Hello World!'); // graph.addVertex('hi there'); // // graph.removeVertex('hi there'); // const pineapple = graph.addVertex('pineapple'); // const banana = graph.addVertex('banana'); // const mango = graph.addVertex('mango', [pineapple]); -// const monkey = graph.addVertex('monkey'); -// const human = graph.addVertex('human'); -// const crocodile = graph.addVertex('crocodile', [human]); -// graph.addEdge(crocodile, monkey); +const monkey = graph.addVertex('monkey'); +const human = graph.addVertex('human'); +const crocodile = graph.addVertex('crocodile', [human]); +graph.addEdge(crocodile, monkey); +console.log('croc edges', crocodile.edges); +console.log('monkey edges', monkey.edges); // graph.removeEdge(monkey, human); -// graph.checkIfEdgeExists(crocodile, monkey); +console.log('check if monkey croc edge exists:'); +graph.checkIfEdgeExists(crocodile, monkey); // const A = graph.addVertex('A'); // const b = graph.addVertex('b'); // graph.removeEdge(A, b); From 8f9ff51eca919da80172dfb4bf71a1c34c458e7e Mon Sep 17 00:00:00 2001 From: Charlie Date: Thu, 1 Feb 2018 16:55:38 -0800 Subject: [PATCH 09/13] CRC: fixed graph addVertex method to connect nodes in passed edges array --- src/graph.js | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/src/graph.js b/src/graph.js index d7d8eb7..b8087be 100644 --- a/src/graph.js +++ b/src/graph.js @@ -41,6 +41,10 @@ class Graph { // Returns the newly-added vertex addVertex(value, edges = []) { let ngn = new GraphNode({ value, edges }); + for (let i = 0; i < edges.length; i++) { + let edgeIndex = this.vertices.indexOf(edges[i]); + this.vertices[edgeIndex].pushToEdges(ngn); + } this.vertices.push(ngn); if (this.vertices.length === 2) { this.vertices[0].pushToEdges(ngn); @@ -121,24 +125,6 @@ class Graph { } } -let graph = new Graph(); -// graph.addVertex('Hello World!'); -// graph.addVertex('hi there'); -// // graph.removeVertex('hi there'); -// const pineapple = graph.addVertex('pineapple'); -// const banana = graph.addVertex('banana'); -// const mango = graph.addVertex('mango', [pineapple]); -const monkey = graph.addVertex('monkey'); -const human = graph.addVertex('human'); -const crocodile = graph.addVertex('crocodile', [human]); -graph.addEdge(crocodile, monkey); -console.log('croc edges', crocodile.edges); -console.log('monkey edges', monkey.edges); -// graph.removeEdge(monkey, human); -console.log('check if monkey croc edge exists:'); -graph.checkIfEdgeExists(crocodile, monkey); -// const A = graph.addVertex('A'); -// const b = graph.addVertex('b'); -// graph.removeEdge(A, b); + module.exports = Graph; From 0629bbcc3bcbee2704d32c8cb2edf13b5956b370 Mon Sep 17 00:00:00 2001 From: Charlie Date: Thu, 1 Feb 2018 17:33:38 -0800 Subject: [PATCH 10/13] CRC: fixed contains to handle empty vertices array, updated removeVertex method to pass to passing --- src/graph.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/graph.js b/src/graph.js index b8087be..1362bcb 100644 --- a/src/graph.js +++ b/src/graph.js @@ -57,10 +57,13 @@ class Graph { // Checks all the vertices of the graph for the target value // Returns true or false contains(value) { + if (this.vertices.length === 0) return false; for (let i = 0; i < this.vertices.length; i++) { - if (this.vertices[i].value === value) return true; - } + if (this.vertices[i].value === value) { + return true; + } return false; + } } // Checks the graph to see if a GraphNode with the specified value exists in the graph // and removes the vertex if it is found @@ -72,9 +75,8 @@ class Graph { for (let i = 0; i < this.vertices.length; i++) { if (this.vertices[i].value === value) { removed = this.vertices[i]; - let newVertices = this.vertices.slice(i, 1); - console.log(newVertices); - console.log(removed.edges); + let newVertices = this.vertices.filter(val => val.value !== value); + this.vertices = newVertices; if (removed.edges) { for (edge in removed.edges) { removeEdge(removed, edge); From adc5096729284bfafcd6fb6c48b04ddbb47315e4 Mon Sep 17 00:00:00 2001 From: Charlie Date: Thu, 1 Feb 2018 20:25:48 -0800 Subject: [PATCH 11/13] CRC: post solution lecture, cleaned up null and unneeded cases, console.logs, added notes and reduce function solutions in comments. 18/18 passing --- src/binary-search-tree.js | 3 --- src/graph.js | 45 ++++++++++++++++++++++----------------- src/tree.js | 16 +++++--------- 3 files changed, 30 insertions(+), 34 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index 4f1e968..f5e6c59 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -38,7 +38,6 @@ class BinarySearchTree { // Can be written recursively or iteratively contains(target) { if (this.value === target) return true; - if (this.value === null) return false; if (target > this.value && this.right !== null) { return this.right.contains(target); } @@ -50,7 +49,6 @@ class BinarySearchTree { // Traverses the tree in a depth-first manner, i.e. from top to bottom // Applies the given callback to each tree node in the process depthFirstForEach(cb) { - if (this.value === null) { return; } cb(this.value); if (this.left) { this.left.depthFirstForEach(cb); @@ -58,7 +56,6 @@ class BinarySearchTree { if (this.right) { this.right.depthFirstForEach(cb); } - if (this.right === null && this.left === null) { return; } } // Traverses the tree in a breadth-first manner, i.e. in layers, starting // at the root node, going down to the root node's children, and iterating diff --git a/src/graph.js b/src/graph.js index 1362bcb..9fa0f38 100644 --- a/src/graph.js +++ b/src/graph.js @@ -50,7 +50,6 @@ class Graph { this.vertices[0].pushToEdges(ngn); this.vertices[1].pushToEdges(this.vertices[0]); } - console.log('vertices are now', this.vertices); return ngn; } @@ -68,6 +67,18 @@ class Graph { // Checks the graph to see if a GraphNode with the specified value exists in the graph // and removes the vertex if it is found // This function should also handle the removing of all edge references for the removed vertex + + // CRC: removeVertex with reduce. + // this.vertices = this.vertices.reduce( (acc, vertex) ) => { + // if (vertex.value === value) { + // vertex.edges.forEach( (edge) => { + // this.removeEdge(item, edge); + // }) + // return acc; + // } + // acc.push(vertex); + // return acc; + // } removeVertex(value) { let removed; if (!this.contains(value)) return; @@ -75,9 +86,9 @@ class Graph { for (let i = 0; i < this.vertices.length; i++) { if (this.vertices[i].value === value) { removed = this.vertices[i]; - let newVertices = this.vertices.filter(val => val.value !== value); + let newVertices = this.vertices.filter(vert => vert.value !== value); this.vertices = newVertices; - if (removed.edges) { + if (removed.edges.length > 0) { for (edge in removed.edges) { removeEdge(removed, edge); } @@ -86,17 +97,17 @@ class Graph { } } } + // Checks the two input vertices to see if each one references the other in their respective edges array // Both vertices must reference each other for the edge to be considered valid // If only one vertex references the other but not vice versa, should not return true // Note: You'll need to store references to each vertex's array of edges so that you can use // array methods on said arrays. There is no method to traverse the edge arrays built into the GraphNode class + // CRC: Can also use includes method on array checkIfEdgeExists(fromVertex, toVertex) { if (fromVertex.edges.indexOf(toVertex) === -1 || toVertex.edges.indexOf(fromVertex) === -1) { - console.log('check edge', fromVertex, toVertex, false); return false; } - console.log('check edge', fromVertex, toVertex, true); return true; } // Adds an edge between the two given vertices if no edge already exists between them @@ -110,23 +121,17 @@ class Graph { // After removing the edge, neither vertex should be referencing the other // If a vertex would be left without any edges as a result of calling this function, those // vertices should be removed as well + // CRC: Solution for getting rid of edge-less vertices using reduce + // this.vertices = this.vertices.reduce( (acc, vertex) => { + // if (vertex.edges.length !== 0) acc.push(vertex); + // return acc; + // }, []) removeEdge(fromVertex, toVertex) { - if (this.checkIfEdgeExists(fromVertex, toVertex)) { - console.log('edge exists'); - let fromIndex = fromVertex.edges.indexOf(toVertex); - fromVertex.edges.splice(fromIndex, 1); - let toIndex = toVertex.edges.indexOf(fromVertex); - toVertex.edges.splice(toIndex, 1); - } - if (!fromVertex.edges) { - this.removeEdge(fromVertex); - } - if (!toVertex.edges) { - this.removeEdge(toVertex); - } + fromVertex.edges = fromVertex.edges.filter( (edge) => edge.value !== toVertex.value ); + toVertex.edges = toVertex.edges.filter( (edge) => edge.value !== fromVertex.value ); + if (fromVertex.numberOfEdges === 0) this.removeVertex(fromVertex.value); + if (toVertex.numberOfEdges === 0) this.removeVertex(toVertex.value); } } - - module.exports = Graph; diff --git a/src/tree.js b/src/tree.js index 23e4a35..8412312 100644 --- a/src/tree.js +++ b/src/tree.js @@ -7,23 +7,17 @@ class Tree { } // Adds a new Tree node with the input value to the current Tree node addChild(value) { - let newChild = new Tree; - newChild.value = value; + let newChild = new Tree(value); this.children.push(newChild); } // Checks this node's children to see if any of them matches the given value // Continues recursively until the value has been found or all of the children // have been checked + // CC - This can also use forEach and call recursively. contains(value) { - if (this.value === value) { - return true; - } - if (this.children) { - let result = false; - for (let i = 0; result === false && i < this.children.length; i++) { - result = this.children[i].contains(value); - } - return result; + if (this.value === value) return true; + for (let i = 0; i < this.children.length; i++) { + if (this.children[i].contains(value)) return true; } return false; } From 285635c9e0d6fce92904d71a029759af7d85cd0f Mon Sep 17 00:00:00 2001 From: Charlie Date: Thu, 1 Feb 2018 20:49:25 -0800 Subject: [PATCH 12/13] CRC: cleaned up linting errors and changed for in loop to forEach, per linter error. 18/18 --- src/binary-search-tree.js | 4 ++-- src/graph.js | 31 ++++++++++++++++--------------- src/tree.js | 2 +- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/binary-search-tree.js b/src/binary-search-tree.js index f5e6c59..919be1e 100644 --- a/src/binary-search-tree.js +++ b/src/binary-search-tree.js @@ -24,7 +24,7 @@ class BinarySearchTree { return; } return this.right.insert(value); - } + } if (value <= this.value) { if (!this.left) { this.left = new BinarySearchTree(value); @@ -64,7 +64,7 @@ class BinarySearchTree { // You'll need the queue-helper file for this. Or could you roll your own queue // again. Whatever floats your boat. breadthFirstForEach(cb) { - let q = new Queue; + const q = new Queue(); if (this.value === null) { return; } q.enqueue(this); let currentNode = this; diff --git a/src/graph.js b/src/graph.js index 9fa0f38..37595d1 100644 --- a/src/graph.js +++ b/src/graph.js @@ -40,9 +40,9 @@ class Graph { // Optionally accepts an array of other GraphNodes for the new vertex to be connected to // Returns the newly-added vertex addVertex(value, edges = []) { - let ngn = new GraphNode({ value, edges }); + const ngn = new GraphNode({ value, edges }); for (let i = 0; i < edges.length; i++) { - let edgeIndex = this.vertices.indexOf(edges[i]); + const edgeIndex = this.vertices.indexOf(edges[i]); this.vertices[edgeIndex].pushToEdges(ngn); } this.vertices.push(ngn); @@ -61,7 +61,7 @@ class Graph { if (this.vertices[i].value === value) { return true; } - return false; + return false; } } // Checks the graph to see if a GraphNode with the specified value exists in the graph @@ -86,17 +86,17 @@ class Graph { for (let i = 0; i < this.vertices.length; i++) { if (this.vertices[i].value === value) { removed = this.vertices[i]; - let newVertices = this.vertices.filter(vert => vert.value !== value); + const newVertices = this.vertices.filter(vert => vert.value !== value); this.vertices = newVertices; - if (removed.edges.length > 0) { - for (edge in removed.edges) { - removeEdge(removed, edge); - } } } + if (removed.edges.length > 0) { + removed.edges.forEach((edge) => { + this.removeEdge(removed, edge); + }); + } } } -} // Checks the two input vertices to see if each one references the other in their respective edges array // Both vertices must reference each other for the edge to be considered valid @@ -105,10 +105,11 @@ class Graph { // array methods on said arrays. There is no method to traverse the edge arrays built into the GraphNode class // CRC: Can also use includes method on array checkIfEdgeExists(fromVertex, toVertex) { - if (fromVertex.edges.indexOf(toVertex) === -1 || toVertex.edges.indexOf(fromVertex) === -1) { - return false; - } - return true; + this.contains(fromVertex); // + if (fromVertex.edges.indexOf(toVertex) === -1 || toVertex.edges.indexOf(fromVertex) === -1) { + return false; + } + return true; } // Adds an edge between the two given vertices if no edge already exists between them // Again, an edge means both vertices reference the other @@ -127,8 +128,8 @@ class Graph { // return acc; // }, []) removeEdge(fromVertex, toVertex) { - fromVertex.edges = fromVertex.edges.filter( (edge) => edge.value !== toVertex.value ); - toVertex.edges = toVertex.edges.filter( (edge) => edge.value !== fromVertex.value ); + fromVertex.edges = fromVertex.edges.filter(edge => edge.value !== toVertex.value); + toVertex.edges = toVertex.edges.filter(edge => edge.value !== fromVertex.value); if (fromVertex.numberOfEdges === 0) this.removeVertex(fromVertex.value); if (toVertex.numberOfEdges === 0) this.removeVertex(toVertex.value); } diff --git a/src/tree.js b/src/tree.js index 8412312..265bf9b 100644 --- a/src/tree.js +++ b/src/tree.js @@ -7,7 +7,7 @@ class Tree { } // Adds a new Tree node with the input value to the current Tree node addChild(value) { - let newChild = new Tree(value); + const newChild = new Tree(value); this.children.push(newChild); } // Checks this node's children to see if any of them matches the given value From 708e73e772379afba0fd8ee46c608cd647e4c8a5 Mon Sep 17 00:00:00 2001 From: Charlie Date: Fri, 2 Feb 2018 01:34:29 -0800 Subject: [PATCH 13/13] CRC: Passing heap, refer to comment - Why doesnt splice work? --- src/heap.js | 49 +++++++++++++++++--- tests/heap.test.js | 108 ++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 60 deletions(-) diff --git a/src/heap.js b/src/heap.js index b317fe1..d6e4c20 100644 --- a/src/heap.js +++ b/src/heap.js @@ -7,38 +7,75 @@ class Heap { // Inserts the given value in the heap // Calls bubbleUp in order to put the newly-inserted element in the right place in the heap insert(val) { - + this.storage.push(val); + this.size++; + let index = this.storage.length - 1; + this.bubbleUp(index); } // Deletes the element located at the front of the heap (the max if a max heap, or a min if a min heap) // Calls siftDown in order to reorganize the heap with a new max/min // In some specifications, this method is also called `poll` delete() { - + const deleted = this.getMax(); + this.storage = [null].concat(this.storage.slice(2)); + // this.storage = this.storage.splice(1,1); Why doesn't this work!? + this.size--; + let index = 1; + while (index <= this.size) { + this.siftDown(index); + index++; + } + return deleted; } // Returns the maximum value in the heap in constant time getMax() { + return this.storage[1]; } // Returns the size of the heap getSize() { - + return this.size; } // Returns the storage array getStorage() { - + return this.storage; } // Moves the element at the specified index "up" by swapping it with its parent // if its parent value is less than the value located at the input index // This method is only used by the heap itself in order to maintain the heap property bubbleUp(index) { - + while (this.storage[index] > this.storage[Math.ceil(index/2)]) { + if (index > 1) { + [this.storage[Math.ceil(index/2)], this.storage[index]] = [this.storage[index], this.storage[Math.ceil(index/2)]]; + if (Math.ceil(index/2) > 1) { + index = Math.ceil(index/2) + } else { break; } + } + } } // First grabs the indices of this element's children and determines which of the children are larger // If the larger of the child elements is larger than the parent, the child element is swapped with the parent // This method is only used by the heap itself in order to maintain the heap property siftDown(index) { - + let child1 = this.storage[Math.ceil(index*2)]; + let c1index = Math.ceil(index*2); + let child2 = this.storage[Math.ceil(index*2 + 1)]; + let c2index = Math.ceil(index*2 + 1); + let greaterChild; + let gcIndex; + if (child1 >= child2 || child2 === undefined) { + greaterChild = child1; + gcIndex = c1index; + } else { + greaterChild = child2; + gcIndex = c2index; // not needed to pass test, but I assume we need? + } + if (greaterChild > this.storage[index]) { + [this.storage[gcIndex], this.storage[index]] = [this.storage[index], this.storage[gcIndex]]; + } } + } + module.exports = Heap; diff --git a/tests/heap.test.js b/tests/heap.test.js index 0ff6902..81f12d7 100644 --- a/tests/heap.test.js +++ b/tests/heap.test.js @@ -1,64 +1,64 @@ -// /* eslint-disable no-undef */ -// const Heap = require('../src/heap'); +/* eslint-disable no-undef */ +const Heap = require('../src/heap'); -// describe('Heap', () => { -// let heap; +describe('Heap', () => { + let heap; -// beforeEach(() => { -// heap = new Heap(); -// }); + beforeEach(() => { + heap = new Heap(); + }); -// it('should have methods named "insert", "delete", "getMax", "getSize", "bubbleUp", and "siftDown"', () => { -// expect(typeof heap.insert).toBe('function'); -// expect(typeof heap.delete).toBe('function'); -// expect(typeof heap.getMax).toBe('function'); -// expect(typeof heap.getSize).toBe('function'); -// expect(typeof heap.bubbleUp).toBe('function'); -// expect(typeof heap.siftDown).toBe('function'); -// }); + it('should have methods named "insert", "delete", "getMax", "getSize", "bubbleUp", and "siftDown"', () => { + expect(typeof heap.insert).toBe('function'); + expect(typeof heap.delete).toBe('function'); + expect(typeof heap.getMax).toBe('function'); + expect(typeof heap.getSize).toBe('function'); + expect(typeof heap.bubbleUp).toBe('function'); + expect(typeof heap.siftDown).toBe('function'); + }); -// it('should get the max value of the heap elements', () => { -// heap.insert(6); -// heap.insert(8); -// heap.insert(10); -// heap.insert(9); -// heap.insert(1); -// heap.insert(9); -// heap.insert(9); -// heap.insert(5); -// expect(heap.getMax()).toEqual(10); -// }); + it('should get the max value of the heap elements', () => { + heap.insert(6); + heap.insert(8); + heap.insert(10); + heap.insert(9); + heap.insert(1); + heap.insert(9); + heap.insert(9); + heap.insert(5); + expect(heap.getMax()).toEqual(10); + }); -// it('should properly get the new max after the old max is deleted', () => { -// heap.insert(6); -// heap.insert(8); -// heap.insert(10); -// heap.insert(9); -// heap.insert(1); -// heap.insert(9); -// heap.insert(9); -// heap.insert(5); + it('should properly get the new max after the old max is deleted', () => { + heap.insert(6); + heap.insert(8); + heap.insert(10); + heap.insert(9); + heap.insert(1); + heap.insert(9); + heap.insert(9); + heap.insert(5); -// heap.delete(); -// expect(heap.getMax()).toEqual(9); -// }); + heap.delete(); + expect(heap.getMax()).toEqual(9); + }); -// it('should delete the elements from greatest to least', () => { -// heap.insert(6); -// heap.insert(7); -// heap.insert(5); -// heap.insert(8); -// heap.insert(10); -// heap.insert(1); -// heap.insert(2); -// heap.insert(5); + it('should delete the elements from greatest to least', () => { + heap.insert(6); + heap.insert(7); + heap.insert(5); + heap.insert(8); + heap.insert(10); + heap.insert(1); + heap.insert(2); + heap.insert(5); -// const descendingOrder = []; -// while (heap.getSize() > 0) { -// descendingOrder.push(heap.delete()); -// } + const descendingOrder = []; + while (heap.getSize() > 0) { + descendingOrder.push(heap.delete()); + } -// expect(descendingOrder).toEqual([10, 8, 7, 6, 5, 5, 2, 1]); -// }); -// }); + expect(descendingOrder).toEqual([10, 8, 7, 6, 5, 5, 2, 1]); + }); +});