Repository: pbiswas101/Mathball (js)

Issue:
Kaprekar Number
### Do the checklist before filing the issue:

- [ ] Is this something you can **debug and fix**?
- [x] Do you have Node.js and all the relevant dev-dependencies installed?
- [ ] Is this a **feature request** that you can add?

###### NOTE: Provide a clear and concise description of the feature that needs to be added! Or if its a bug, then provide the necessary steps to reproduce it.

- *Give your answer below:*

------------

[Function: **M.isKaprekar()**] needs to be added!
For more info:

https://www.geeksforgeeks.org/kaprekar-number/

*M.isKaprekar()* needs to accept a positive integer and all other arguments passed should throw a type error which needs to be handled gracefully! For error handling, you should refer to how other features like M.isArmstrong() is implemented.

Pull request description:
Add graphs
### Do the checklist before submitting the PR:

- [x] Have you read the guidelines mentioned in **CONTRIBUTING.md**?
- [x] Have you squashed your commits?

**Q**: What version of *Node.js* you've used in the project? (`e.g. Node v10.11.0`)
**A**:v11.6.0
**Q**: Mention the *Issue Number*! (`e.g. Fixed #8`)
**A**:#69

- *Give additional information regarding the PR below:*

------------


Patch:
diff --git a/README.md b/README.md
index c07b320..22f8d97 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ $ npm install mathball --save
 
 - **Mathematical Utilities** - [Complex][49] - [frequency][40] - [gcd][10] - [getAllPerm][55] - [isEven][11] - [isOdd][12] - [lcm][13] - [length][14] - [max][15] - [min][16] - [modInv][39] - [nCr][48] - [pow][46] - [sort][17] - [sum][18] - [toDegrees][50] - [toRadians][51]
 
-- **Data Structures** - [priorityQueue][44] - [stack][53]
+- **Data Structures** - [priorityQueue][44] - [stack][53] - [graph][57]
 
 - **Helper Methods** - [performance][28] - [pipe][29]
 
@@ -122,3 +122,4 @@ The MIT License 2019 - [Priyabrata Biswas][20].
 [54]: https://github.com/pbiswas101/Mathball/blob/master/src/isHoax/index.js
 [55]: https://github.com/pbiswas101/Mathball/blob/master/src/permutation/index.js
 [56]: https://github.com/pbiswas101/Mathball/blob/master/src/ugly/index.js
+[57]: https://github.com/pbiswas101/Mathball/blob/master/src/graph/index.js
diff --git a/src/graph/index.js b/src/graph/index.js
new file mode 100644
index 0000000..f7b4b14
--- /dev/null
+++ b/src/graph/index.js
@@ -0,0 +1,89 @@
+class Graph{
+    constructor(vertices){
+        this.noOfVertices = vertices;
+        this.Adjlist = new Map();
+    }
+
+    addVertex(vertexData){
+        return this.Adjlist.set(vertexData, []);
+    }
+
+    addEdge(source, destination){
+        return this.Adjlist.get(source).push(destination);
+    }
+
+    printGraph(){
+        return this.Adjlist;
+    }
+
+    removeVertex(vertexName){
+        if(this.Adjlist.size === 0)
+        {
+            return "Empty Graph";
+        }
+        else{
+            return this.Adjlist.delete(vertexName);
+        }
+    }
+
+    removeEdge(vertexName, edgeName){
+        
+        if(this.Adjlist.size === 0)
+        {
+            return "Empty Graph";
+        }
+        
+        if(!this.Adjlist.get(vertexName))
+        {
+            return "Vertex does not exist in the Graph";
+        }
+        
+        let location = this.Adjlist.get(vertexName).indexOf(edgeName);
+
+        if(location === -1){
+            return "Edge not found!";
+        }
+        else{
+            return this.Adjlist.get(vertexName).splice(location, 1).toString();
+        }
+        
+    }
+
+    bfs(startNode){
+        
+        if(!Array.from(this.Adjlist.keys()).includes(startNode)){
+            return "Node doesn't exist in the Graph";
+        }
+        let visited = [];
+        let output = new Array();
+
+        for(let i = 0; i < this.noOfVertices; i++){
+            visited.push(false);
+        }
+        let queue = [];
+
+        visited[startNode] = true;
+        queue.push(startNode);
+
+        while(queue.length > 0){
+            let getQueueElement = queue.shift();
+            output.push(getQueueElement);
+            
+            let getList =  this.Adjlist.get(getQueueElement);
+
+            for(let i = 0; i < getList.length; i++){
+                
+                let neighbour = getList[i];
+                
+                if(!visited[neighbour]){
+                    
+                    visited[neighbour] = true;
+                    queue.push(neighbour);
+                }
+            }
+        }
+        return output;
+    }
+}
+
+module.exports = Graph;
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index cd38dd8..90019b0 100644
--- a/src/index.js
+++ b/src/index.js
@@ -50,7 +50,8 @@ const performance = require('./performance'),
 
 /* Data Structure */
 const PriorityQueue = require('./PriorityQueue'),
-	Stack = require('./stack');
+	Stack = require('./stack'),
+	Graph = require('./graph');
 
 /* M - Mathball Object */
 module.exports = {
@@ -96,6 +97,7 @@ module.exports = {
 	isDeficient,
 	PriorityQueue,
 	Stack,
+	Graph,
 	isCarmichael: carmichael.isCarmichael,
 	rangeFibonacci: fibonacci.rangeFibonacci,
 	Complex,


Test patch:
diff --git a/test/graph-spec.js b/test/graph-spec.js
new file mode 100644
index 0000000..0e13ba6
--- /dev/null
+++ b/test/graph-spec.js
@@ -0,0 +1,98 @@
+const assert = require('assert'),
+    Graph = require('../src/graph'),
+    sample = new Graph(5);
+
+    describe('[Function: Graph]', () => {
+
+        it('should be a function', () => {
+            assert.strictEqual(typeof Graph, 'function');
+        });
+        
+        it(`should return 'Empty Graph' when 'removeVertex()' is called`, () => {
+            assert.strictEqual(sample.removeVertex('A'), 'Empty Graph');
+        });
+        
+        it(`should return 'Empty Graph' when 'removeEdge()' is called`, () => {
+            assert.strictEqual(sample.removeEdge('A', 'B'), 'Empty Graph');
+        });
+        
+        it(`should return 'object' when 'sample.addVertex('A')' is called`, () => {
+            assert.strictEqual(typeof sample.addVertex('A'), 'object');
+        });
+
+        it(`should return 'object' when 'sample.addVertex('B')' is called`, () => {
+            assert.strictEqual(typeof sample.addVertex('B'), 'object');
+        });
+
+        it(`should return 'object' when 'sample.addVertex('C')' is called`, () => {
+            assert.strictEqual(typeof sample.addVertex('C'), 'object');
+        });
+
+        it(`should return 'object' when 'sample.addVertex('D')' is called`, () => {
+            assert.strictEqual(typeof sample.addVertex('D'), 'object');
+        });
+        
+        it(`should return 'object' when 'sample.addVertex('E')' is called`, () => {
+            assert.strictEqual(typeof sample.addVertex('E'), 'object');
+        });
+        
+        it(`should return 'number' when 'sample.addEdge('A', 'B')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('A', 'B'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('D', 'E')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('D', 'E'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('C', 'E')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('C', 'E'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('A', 'D')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('A', 'D'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('A', 'C')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('A', 'C'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('E', 'B')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('E', 'B'), 'number');
+        });
+
+        it(`should return 'number' when 'sample.addEdge('D', 'B')' is called`, () => {
+            assert.strictEqual(typeof sample.addEdge('D', 'B'), 'number');
+        });
+       
+        it(`should return an 'object' when 'printGraph()' is called`, () => {
+            assert.strictEqual(typeof sample.printGraph(), 'object');
+        });
+    
+        it(`should return 'Vertex does not exist in the Graph' when 'removeEdge('Z', 1)' is called`, () => {
+            assert.strictEqual(sample.removeEdge('Z', 1), 'Vertex does not exist in the Graph');
+        });
+        
+        it(`should return 'Edge not found!' when 'removeEdge('B', 9)' is called`, () => {
+            assert.strictEqual(sample.removeEdge('B', 9), 'Edge not found!');
+        });
+
+        it(`should return 'object' type when 'bfs('A')' is called`, () => {
+            assert.strictEqual(typeof sample.bfs('A'), 'object');
+        });
+
+        it(`should return '[ 'A', 'B', 'D', 'C', 'E' ]' type when 'bfs('A')' is called`, () => {
+            assert.deepEqual(sample.bfs('A'), ["A", "B", "D", "C", "E"]);
+        });
+        
+        it(`should return 'Node doesn't exist in the Graph' when 'bfs('f')' is called`, () => {
+            assert.deepEqual(sample.bfs('f'), 'Node doesn\'t exist in the Graph');
+        });
+        
+        it(`should return 'D' when 'removeEdge('A', 'D')' is called`, () => {
+            assert.strictEqual(sample.removeEdge('A', 'D'), 'D');
+        });
+
+        it(`should return 'true' when 'removeVertex(A)' is called`, () => {
+            assert.strictEqual(sample.removeVertex('A'), true);
+        });
+    });
\ No newline at end of file