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:
Matrix Chain Multiplication
*Added Matrix Chain Multiplication function

*Added Matrix Chain Multiplication in index and readme

*Added Unit Tests in matrixChain-spec

### Do the checklist before submitting the PR:

- [:heavy_check_mark:] Have you read the guidelines mentioned in **CONTRIBUTING.md**?
- [:heavy_check_mark:] 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.10.1

**Q**: Mention the *Issue Number*! (`e.g. Fixed #8`)
**A**:#104

- *Give additional information regarding the PR below:*

------------


Patch:
diff --git a/README.md b/README.md
index 30db972..af3b654 100644
--- a/README.md
+++ b/README.md
@@ -30,7 +30,7 @@ $ npm install mathball --save
 
 - **Range of Numbers** - [rangePrime][7] - [rangeFibonacci][8] - [rangePalindrome][6]
 
-- **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] - [matrixMultiply][58] - [matrixExpo][59]
+- **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] - [matrixMultiply][58] - [matrixExpo][59] - [matrixChain][60]
 
 - **Data Structures** - [priorityQueue][44] - [stack][53] - [graph][57]
 
@@ -127,4 +127,5 @@ The MIT License 2019 - [Priyabrata Biswas][20].
 [56]: https://github.com/pbiswas101/Mathball/blob/master/src/ugly/index.js
 [57]: https://github.com/pbiswas101/Mathball/blob/master/src/graph/index.js
 [58]: https://github.com/pbiswas101/Mathball/blob/master/src/matrixMultiply/index.js
-[59]: https://github.com/pbiswas101/Mathball/blob/master/src/matrixExponentiation/index.js
\ No newline at end of file
+[59]: https://github.com/pbiswas101/Mathball/blob/master/src/matrixExponentiation/index.js
+[60]: https://github.com/pbiswas101/Mathball/blob/master/src/matrixChain/index.js
\ No newline at end of file
diff --git a/src/index.js b/src/index.js
index 04ce4fc..db4b063 100644
--- a/src/index.js
+++ b/src/index.js
@@ -38,6 +38,7 @@ const frequency = require('./frequency'),
 	min = require('./min'),
 	modInv = require('./modInv'),
 	matrixMultiply = require('./matrixMultiply'),
+	matrixChain = require('./matrixChain'),
 	matrixExpo = require('./matrixExponentiation'),
 	pow = require('./pow'),
 	sort = require('./sort'),
@@ -76,6 +77,7 @@ module.exports = {
 	isLucky: lucky.isLucky,
 	magic: magic.magic,
 	matrixMultiply,
+	matrixChain: matrixChain.matrixChain,
 	matrixExpo: matrixExpo.matrixExpo,
 	max,
 	min,
diff --git a/src/matrixChain/index.js b/src/matrixChain/index.js
new file mode 100644
index 0000000..9f1450c
--- /dev/null
+++ b/src/matrixChain/index.js
@@ -0,0 +1,33 @@
+/*Matrix Chain Multiplication
+*Function: M.matrixChain([])
+*/
+
+const validate = require('../validation/integer-array');
+
+const matrixChain = (ar) => {
+	let n = ar.length;
+	let m = [...Array(n)].map(x => Array(n).fill(0));
+	let cost, j;
+
+	for(let i = 0; i < n; i++){
+		m[i][i] = 0;
+}
+	for(let l = 2; l < n; l++){
+		for(let i = 1; i < (n-l+1); i++){
+			j = i + l - 1;
+			m[i][j] = Number.MAX_SAFE_INTEGER;
+			for(let k = i; k <= j-1; k++){
+				cost = m[i][k] + m[k+1][j] +
+						(ar[i-1]*ar[k]*ar[j]);
+				if(cost < m[i][j]){
+					m[i][j] = cost;}
+			}
+		}
+	}
+return m[1][n-1];
+};
+
+exports.matrixChain = (arr) => {
+	validate(arr, 'matrixChain');
+	return matrixChain(arr);
+};


Test patch:
diff --git a/test/matrixChain-spec.js b/test/matrixChain-spec.js
new file mode 100644
index 0000000..b08b938
--- /dev/null
+++ b/test/matrixChain-spec.js
@@ -0,0 +1,38 @@
+const assert = require('assert'),
+	matrixChain = require('../src/matrixChain').matrixChain;
+
+describe('[Function: matrixChain]', () => {
+		assert.strictEqual(typeof matrixChain, 'function');
+
+	it('should return 4500 when [10,30,5,60] is passed', () => {
+		assert.strictEqual(matrixChain([10,30,5,60]), 4500);
+	});
+
+	it('should return 14000 when [40,20,30,10] is passed', () => {
+		assert.strictEqual(matrixChain([40,20,30,10]), 14000);
+	});
+
+	it('should return 78 when [2,3,5,2,4,3] is passed', () => {
+		assert.strictEqual(matrixChain([2,3,5,2,4,3]), 78);
+	});
+
+	it('should throw a TypeError when just an integer is passed', () => {
+		assert.throws(() => matrixChain(20), TypeError);
+	});
+
+	it('should throw a TypeError when a negative number is passed in the array', () => {
+		assert.throws(() => matrixChain([10,-20, -40,20]), TypeError);
+	});
+
+	it('should throw an error for string input', () => {
+		assert.throws(() => matrixChain(['10','20','30']), TypeError);
+	});
+
+	it('should not accept a floating point', () => {
+		assert.throws(() => matrixChain([1.3, 4.5, 5.4, 6.7]), TypeError);
+	});
+
+	it('should not accept a boolean', () => {
+		assert.throws(() => matrixChain([true, false, true, false]), TypeError);
+	});
+});