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:
documentation for M.phi() added
### 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**: v10.15.3

**Q**: Mention the *Issue Number*! (`e.g. Fixed #8`)
**A**:  #167 

- *Give additional information regarding the PR below:*

documentation for M.phi() added


Patch:
diff --git a/docs/Euler's Totient/index.md b/docs/Euler's Totient/index.md
index e69de29..2b66af6 100644
--- a/docs/Euler's Totient/index.md
+++ b/docs/Euler's Totient/index.md
@@ -0,0 +1,40 @@
+# Euler's Totient </br>  
+The ``` M.phi() ``` function for an input n returns count of numbers in {1, 2, 3, …, n} that are relatively prime to n, i.e., the numbers whose GCD (Greatest Common Divisor) with n is 1   
+
+### Syntax  
+> M.phi(num)  
+
+### Arguments  
+> Number  
+	
+### Return  
+> Number  
+	
+### Examples  
+- Valid:  
+	```js
+	M.phi(9);                                // 6
+	M.phi(0);                                // 0
+	M.phi(10)                                // 4 
+	```  
+- Invalid:  
+	```js
+	/*
+	 * TypeError: Invalid argument received: <argument>
+	 * 'phi()' only accept a non-negative-integer!
+	 */
+	M.phi("31")
+	M.phi(true)
+  M.phi(31.101996)
+  M.phi(-20)
+  M.phi(0)
+	```
+
+### Info:
+Implemented using Euler’s product formula.
+
+------
+
+
+
+
diff --git a/src/Matrix/index.js b/src/Matrix/index.js
index abe546f..d9d2804 100644
--- a/src/Matrix/index.js
+++ b/src/Matrix/index.js
@@ -119,6 +119,53 @@ class Matrix{
 		integerValidate(a, 'pow');
 		return matrixExpo(this.args, a);
 	}
+
+	
+	transpose() {
+		let arr = this.args;
+		const col = arr.length;
+		const row = arr[0].length;
+		let tarr = [];
+
+		for (let i = 0; i < row; i++) {
+			tarr[i] = [];
+		}
+		for (let i = 0; i < row; i++) {
+			for (let j = 0; j < col; j++) {
+				tarr[i][j] = arr[j][i];
+			}
+		}
+		return tarr;
+	}
+
+	sort(type, order = true) {
+		stringValidate(type, 'sort');
+		if(type != 'row' && type!='col'){
+			throw new TypeError(`Invalid argument received: ${JSON.stringify(type)}\n'sort(arg1,arg2)' only accepts row or col as arg1!\n`);
+		}	
+		if(typeof order != 'boolean'){
+			throw new TypeError(`Invalid argument received: ${JSON.stringify(order)}\n'sort(arg1,arg2)' only accepts a boolean as arg2!\n`);
+		}	
+
+		switch (type) {
+			case 'row':
+				let arr = this.args;
+				for (let i = 0; i < arr.length; i++) {
+					arr[i].sort((prev, next) => order ? prev - next : next - prev);
+				}
+				this.args = arr;
+				return arr;
+
+			case 'col':
+				this.args = this.transpose();
+				let tarr = this.args;
+				for (let i = 0; i < this.args.length; i++) {
+					tarr[i].sort((prev, next) => order ? prev - next : next - prev);
+				}
+				this.args = this.transpose();
+				return this.args;
+		}
+	}
 }
 
 module.exports = Matrix;


Test patch:
diff --git a/test/Matrix-spec.js b/test/Matrix-spec.js
index 7bcc965..afabc2a 100644
--- a/test/Matrix-spec.js
+++ b/test/Matrix-spec.js
@@ -1,6 +1,7 @@
 const assert = require('assert'),
 	Matrix = require('../src/Matrix'),
 	x = new Matrix([[1,2],[3,4]]),
+	y = new Matrix([[4, 7, 1], [3, 2, -1]]),
 	f = new Matrix([[1,0,0],[0,0,1]]),
 	upper = new Matrix([[1,2,3,4],[0,1,2,3],[0,0,1,2],[0,0,0,1]]),
 	lower = new Matrix([[1,0,0,0],[1,2,0,0],[1,2,3,0],[1,2,3,4]]),
@@ -123,4 +124,51 @@ describe('[Function: Matrix]', () => {
 			const z = new Matrix([[3,4], ['4','5']]);
 		}, TypeError);
 	});
+
+	it('should return [[4,3],[7,2],[1,-1]] when transpose() is called', () => {
+		assert.deepStrictEqual(y.transpose(), [[4, 3], [7, 2], [1, -1]]);
+	});
+
+	it('should return [[1,4,7],[-1,2,3]] when sort is called with \'row\'', () => {
+		assert.deepStrictEqual(y.sort('row'), [[1, 4, 7], [-1, 2, 3]]);
+	});
+
+	it('should return [[-1,2,3 ],[1,4,7]] when sort is called with \'col\'', () => {
+		assert.deepStrictEqual(y.sort('col'), [[ -1, 2, 3 ],[ 1, 4, 7 ]]);
+
+	});
+
+
+	it('should return [[ 1,4,7 ],[ -1,2,3 ]] when sort is called with \'col\' and false', () => {
+		assert.deepStrictEqual(y.sort('col',false), [[ 1, 4, 7 ],[ -1, 2, 3 ]]);
+
+	});
+
+
+	it('should return [[ 7, 4, 1 ],[ 3, 2, -1 ]] when sort is called with \'row\' and false', () => {
+		assert.deepStrictEqual(y.sort('row',false), [[ 7, 4, 1 ],[ 3, 2, -1 ]]);
+
+	});
+
+	it('should return TypeError when sort is called with invalid second argument', () => {
+		assert.throws(() => y.sort('row',123), TypeError);
+
+	});
+
+	it('should throw a TypeError when invalid type is passed for sort()', () => {
+		assert.throws(() => {
+			const z = new Matrix([[3, 4], ['4', '5']]);
+			z.sort(true);
+		}, TypeError);
+	});
+
+	it('should throw an error if invalid type is passed to sort()', () => {
+		assert.throws(() => x.sort('cosds'), TypeError);
+	});
+
+	it('should throw an error if no argument is passed to sort()', () => {
+		assert.throws(() => x.sort(), TypeError);
+	});
 });
+
+