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:
Adding Binary tree feature. Issue #158
### 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**:Added #158

- *Give additional information regarding the PR below:*

------------


Patch:
diff --git a/README.md b/README.md
index bd7c4d2..1346588 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@ $ npm install mathball --save
 
 - **Core Tools** - [Absolute][8] - [Add][9] - [Average][10] - [Binomial Coeff][11] - [Convert][12] - [Count][13] - [Divide][14] - [Euler's Totient][15] - [Modular Exponent][16] - [GCD][17] - [LCM][18] - [Length][19] - [Maximum][20] - [Median][21] - [Minimum][22] - [Modular Inverse][23] - [Multiply][24] - [Permute][25] - [Set Bits][26] - [Sort][27] - [Subtract][28] - [Sum][29]
 
-- **Data Structures** - [Graph][30] - [Matrix][31] - [Priority Queue][32] - [Stack][33]
+- **Data Structures** - [Graph][30] - [Matrix][31] - [Priority Queue][32] - [Stack][33] - [BinaryTree][37]
 
 ## Examples
 
@@ -96,3 +96,4 @@ The MIT License 2019 - [Priyabrata Biswas][36].
 [34]: https://github.com/pbiswas101/Mathball/blob/master/CONTRIBUTING.md
 [35]: https://www.gssoc.tech/
 [36]: https://github.com/pbiswas101
+[37]: https://github.com/pbiswas101/Mathball/blob/master/docs
\ No newline at end of file
diff --git a/src/binary-tree/index.js b/src/binary-tree/index.js
new file mode 100644
index 0000000..b98e1a4
--- /dev/null
+++ b/src/binary-tree/index.js
@@ -0,0 +1,162 @@
+class Node{
+    constructor(data){
+        this.data = data;
+        this.rightChild = null;
+        this.leftChild = null;
+    }
+}
+
+class BinaryTree{
+    constructor(){
+        this.root = null;
+    }
+
+    insert(data){
+        let newNode = new Node(data);
+        if(this.root === null){
+            this.root = newNode;
+        }
+        else{
+            this.insertNode(this.root, newNode);
+        }
+        return newNode;
+    }
+
+    insertNode(parent, node){
+        if(node.data < parent.data){
+            if(parent.leftChild === null){
+                parent.leftChild = node;
+            }
+            else{
+                this.insertNode(parent.leftChild, node);
+            }
+        }
+        else{
+            if(parent.rightChild === null){
+                parent.rightChild = node;
+            }
+            else{
+                this.insertNode(parent.rightChild, node);
+            }
+        }
+    }
+
+    remove(data){
+        if(this.root === null){
+            return "Empty Tree";
+        }
+        this.root = this.removeNode(this.root, data);
+        return data;
+    }
+
+    removeNode(node, data){
+    
+        if(data < node.data){
+            node.leftChild = this.removeNode(node.leftChild, data);
+            return node;
+        }
+        else if(data > node.data){
+            node.rightChild = this.removeNode(node.rightChild, data);
+            return node;
+        }
+        else{
+            if(node.leftChild === null && node.rightChild === null){
+                node = null;
+                return node;
+            }
+
+            else if(node.leftChild === null){
+                node = node.rightChild;
+                return node;
+            }
+
+            else if(node.rightChild === null){
+                node = node.leftChild;
+                return node;
+            }
+
+            else{
+                let smallestReplacement = this.findMin(node.rightChild);
+                node.data = smallestReplacement.data;
+                
+                node.rightChild = this.removeNode(node.rightChild, smallestReplacement.data);
+                return node;
+            }
+        }
+    }
+
+    //Recursively find the smallest element in the tree
+    findMin(node){
+        if(node === null){
+            return "Empty Tree!";
+        }
+        
+        else if(node.leftChild === null){
+            return node.data;
+        }
+
+        else{
+            return this.findMin(node.leftChild);
+        }
+    }
+
+    //Recursively find the largest element in the tree
+    findMax(node){
+        if(node === null){
+            return "Empty Tree!";
+        }
+
+        else if(node.rightChild === null){
+            return node.data;
+        }
+
+        else{
+            return this.findMax(node.rightChild);
+        }
+    }
+
+    //Traversals
+    inOrder(node){
+        let traversal = [];
+        this.inOrderTraverse(node, traversal);
+        return traversal;
+    }
+
+    inOrderTraverse(node, traversal){
+       if(node !== null){
+            this.inOrderTraverse(node.leftChild, traversal);
+            traversal.push(node.data);
+            this.inOrderTraverse(node.rightChild, traversal);
+       }
+    }
+
+    preOrder(node){
+        let traversal = [];
+        this.preOrderTraverse(node, traversal);
+        return traversal;
+    }
+    
+    preOrderTraverse(node, traversal){
+        if(node !== null){
+            traversal.push(node.data);
+            this.preOrderTraverse(node.leftChild, traversal);
+            this.preOrderTraverse(node.rightChild, traversal);
+        }
+    }
+
+    postOrder(node){
+        let traversal = [];
+        this.postOrderTraverse(node, traversal);
+        return traversal;
+    }
+    
+    postOrderTraverse(node, traversal){
+        if(node !== null){
+            this.postOrderTraverse(node.leftChild, traversal);
+            this.postOrderTraverse(node.rightChild, traversal);
+            traversal.push(node.data);
+        }
+    }
+}
+
+module.exports = BinaryTree;
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 04c000e..28bfa7b 100644
--- a/src/index.js
+++ b/src/index.js
@@ -34,7 +34,7 @@ const abs = require('./absolute'),
 
 /* Data Structures */
 const Matrix = require('./Matrix'),
-	/*=====*/
+	BinaryTree = require('./binary-tree'),
 	Graph = require('./graph'),
 	PriorityQueue = require('./priority-queue'),
 	Stack = require('./stack');
@@ -69,6 +69,7 @@ module.exports = {
 	avg,
 	inverse,
 	count,
+	BinaryTree,
 	PriorityQueue,
 	Stack,
 	Graph,


Test patch:
diff --git a/test/binarytree-spec.js b/test/binarytree-spec.js
new file mode 100644
index 0000000..274b29b
--- /dev/null
+++ b/test/binarytree-spec.js
@@ -0,0 +1,100 @@
+const assert = require('assert'),
+        BinaryTree = require('../src/binary-tree'),
+        tree = new BinaryTree();
+
+    describe('[function: BinaryTree]', () => {
+        it("should be a function", () => {
+            assert.strictEqual(typeof BinaryTree, 'function');
+        });
+
+        it('should return "Empty Tree" when remove() is called', () => {
+            assert.strictEqual(tree.remove(0), "Empty Tree");
+        });
+
+        it('should return "-10" when findMin is called', () => {
+            assert.strictEqual(tree.findMin(tree.root), "Empty Tree!");
+        });
+
+        it('should return "100" when findMax is called', () => {
+            assert.strictEqual(tree.findMax(tree.root), "Empty Tree!");
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(0), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(-1), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(10), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(-10), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(-0.5), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(5), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(12), 'object');
+        });
+
+        it('should return "[ -10, -1, -0.5, 0, 5, 10, 12 ]" when inOrder is called', () => {
+            assert.deepEqual(tree.inOrder(tree.root), [-10, -1, -0.5, 0, 5, 10, 12]);
+        });
+
+        it('should return "[ -10, -0.5, -1, 5, 12, 10, 0 ]" when postOrder is called', () => {
+            assert.deepEqual(tree.postOrder(tree.root), [-10, -0.5, -1, 5, 12, 10, 0]);
+        });
+
+        it('should return "[ 0, -1, -10, -0.5, 10, 5, 12 ]" when preOrder is called', () => {
+            assert.deepEqual(tree.preOrder(tree.root), [0, -1, -10, -0.5, 10, 5, 12]);
+        });
+
+        it('should return "-10" when findMin is called', () => {
+            assert.strictEqual(tree.findMin(tree.root), -10);
+        });
+
+        it('should return "12" when findMax is called', () => {
+            assert.strictEqual(tree.findMax(tree.root), 12);
+        });
+
+        it('should return "5" when remove is called', () => {
+            assert.strictEqual(tree.remove(5, tree.root), 5);
+        }); 
+        
+        it('should return "10" when remove is called', () => {
+            assert.strictEqual(tree.remove(10, tree.root), 10);
+        });  
+
+        it('should return "-0.5" when remove is called', () => {
+            assert.strictEqual(tree.remove(-0.5, tree.root), -0.5);
+        });  
+
+        it('should return "-1" when remove is called', () => {
+            assert.strictEqual(tree.remove(-1, tree.root), -1);
+        });  
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(10), 'object');
+        });
+        
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(6), 'object');
+        });
+
+        it('should return an object when insert is called', () => {
+            assert.strictEqual(typeof tree.insert(11), 'object');
+        });
+
+        it('should return "10" when remove is called', () => {
+            assert.strictEqual(tree.remove(10, tree.root), 10);
+        });  
+    });
\ No newline at end of file