You are provided with marks of N students in Physics, Chemistry and Maths.
Perform the following 3 operations: 
	Sort the students in Ascending order of their Physics marks.
	Once this is done, sort the students having same marks in Physics in the descending order of their Chemistry marks.
	Once this is also done, sort the students having same marks in Physics and Chemistry in the ascending order of their Maths marks.
Example 1:
Input:
N = 10
phy[] = {4 1 10 4 4 4 1 10 1 10}
chem[] = {5 2 9 6 3 10 2 9 14 10}
math[] = {12 3 6 5 2 10 16 32 10 4}
Output:
1 14 10
1 2 3
1 2 16
4 10 10
4 6 5
4 5 12
4 3 2
10 10 4
10 9 6
10 9 32
Explanation: Firstly, the Physics marks of 
students are sorted in ascending order.
Those having same marks in Physics have
their Chemistry marks in descending order.
Those having same marks in both Physics
and Chemistry have their Math marks in
ascending order.
Your Task:
You don't need to read input or print anything. Your task is to complete the function customSort() which takes  phy[],  chem[],  math[]  and an integer N denoting the marks and the number of students. The function sorts the marks in the described order and the final changes should be made in the given arrays only.
Expected Time Complexity: O(NLogN).
Expected Auxiliary Space: O(N).
Constraints:
1 <= N <= 10000

Difficulty: MEDIUM
Tags: Sorting

Data structures
Skill types: Sorting

Data structures
Expected Time Complexity: O(NLogN).
Expected Auxiliary Space: O(N).

Starter code:
#User function Template for python3

class Solution:
    def customSort(self, phy, chem, math, N):
        # code here

Solutions:
class Solution:

	def customSort(self, phy, chem, math, N):
		mark = []
		for i in range(N):
			mark.append((phy[i], chem[i], math[i]))
		mark.sort(key=lambda x: (x[0], -x[1], x[2]))
		for i in range(N):
			(phy[i], chem[i], math[i]) = mark[i]


class Node:

	def __init__(self, phy, chem, maths):
		self.phy = phy
		self.chem = chem
		self.maths = maths

	def __gt__(self, other):
		if self.phy < other.phy:
			return False
		elif self.phy > other.phy:
			return True
		if self.chem < other.chem:
			return True
		elif self.chem > other.chem:
			return False
		if self.maths < other.maths:
			return False
		elif self.maths > other.maths:
			return True
		else:
			return False

class Solution:

	def customSort(self, phy, chem, math, N):
		new = []
		for i in range(N):
			new.append(Node(phy[i], chem[i], maths[i]))
		new.sort()
		for i in range(N):
			phy[i] = new[i].phy
			chem[i] = new[i].chem
			maths[i] = new[i].maths


class Solution:

	def __init__(self, p=0, c=0, m=0):
		self.p = p
		self.c = c
		self.m = m

	def add(self, p, c, m):
		self.p = p
		self.c = c
		self.m = m

	def customSort(self, phy, chem, math, N):
		arrl = []
		for i in range(N):
			arrl.append(Solution(phy[i], chem[i], math[i]))

		def compare(s1, s2):
			if s1.p < s2.p:
				return -1
			elif s1.p > s2.p:
				return 1
			elif s1.c < s2.c:
				return 1
			elif s1.c > s2.c:
				return -1
			elif s1.m < s2.m:
				return -1
			elif s1.m > s2.m:
				return 1
			else:
				return 0
		arrl.sort(key=lambda x: (x.p, -x.c, x.m))
		for i in range(N):
			phy[i] = arrl[i].p
			chem[i] = arrl[i].c
			math[i] = arrl[i].m


class Solution:

	def customSort(self, phy, chem, math, N):
		stu = [[phy[x], chem[x], math[x]] for x in range(N)]
		stu.sort(key=lambda m: [m[0], -m[1], m[2]])
		for x in range(N):
			phy[x] = stu[x][0]
			chem[x] = stu[x][1]
			math[x] = stu[x][2]


class Solution:

	def customSort(self, phy, chem, math, N):
		marks = [(phy[i], chem[i], math[i]) for i in range(N)]
		marks.sort(key=lambda x: x[2])
		marks.sort(key=lambda x: x[1], reverse=True)
		marks.sort(key=lambda x: x[0])
		for i in range(N):
			phy[i] = marks[i][0]
			chem[i] = marks[i][1]
			math[i] = marks[i][2]
		return


class Node:

	def __init__(self, a, b, c):
		self.phy = a
		self.chem = b
		self.math = c

	def __gt__(self, other):
		if self.phy < other.phy:
			return False
		elif self.phy > other.phy:
			return True
		if self.chem < other.chem:
			return True
		elif self.chem > other.chem:
			return False
		if self.math < other.math:
			return False
		elif self.math > other.math:
			return True
		else:
			return False

class Solution:

	def customSort(self, phy, chem, math, N):
		elements = []
		for i in range(N):
			elements.append(Node(phy[i], chem[i], math[i]))
		elements.sort()
		for i in range(N):
			phy[i] = elements[i].phy
			chem[i] = elements[i].chem
			math[i] = elements[i].math


class Solution:

	def customSort(self, phy, chem, math, N):
		records = [[phy[i], chem[i], math[i]] for i in range(N)]
		records.sort(key=lambda x: [x[0], -1 * x[1], x[2]])
		for i in range(N):
			phy[i] = records[i][0]
			chem[i] = records[i][1]
			math[i] = records[i][2]
		return


import heapq

class Solution:

	def customSort(self, phy, chem, math, N):
		pq = []
		for i in range(N):
			heapq.heappush(pq, (phy[i], -chem[i], math[i]))
		count = 0
		while len(pq) > 0:
			sub = heapq.heappop(pq)
			(phy[count], chem[count], math[count]) = (sub[0], -sub[1], sub[2])
			count += 1
if __name__ == '__main__':
	t = int(input())
	for _ in range(t):
		n = int(input().strip())
		phy = []
		chem = []
		maths = []
		for i in range(n):
			marks = [int(x) for x in input().strip().split(' ')]
			phy.append(marks[0])
			chem.append(marks[1])
			maths.append(marks[2])
		ob = Solution()
		ob.customSort(phy, chem, maths, n)
		for i in range(n):
			print(phy[i], chem[i], maths[i])


from heapq import *

class Solution:

	def customSort(self, phy, chem, math, N):
		ans = []
		for i in range(N):
			heappush(ans, (phy[i], -chem[i], math[i]))
		res = []
		c = 0
		while ans:
			sub = heappop(ans)
			(phy[c], chem[c], math[c]) = (sub[0], -sub[1], sub[2])
			c += 1
if __name__ == '__main__':
	t = int(input())
	for _ in range(t):
		n = int(input().strip())
		phy = []
		chem = []
		maths = []
		for i in range(n):
			marks = [int(x) for x in input().strip().split(' ')]
			phy.append(marks[0])
			chem.append(marks[1])
			maths.append(marks[2])
		ob = Solution()
		ob.customSort(phy, chem, maths, n)
		for i in range(n):
			print(phy[i], chem[i], maths[i])


class Solution:

	def radix(self, T, x, order):
		if order == 0:
			T.sort(key=lambda k: k[x])
		elif order == 1:
			T.sort(key=lambda k: k[x])
			T.reverse()

	def customSort(self, phy, chem, math, N):
		grades = [[] for _ in range(N)]
		for i in range(N):
			grades[i].append(phy[i])
			grades[i].append(chem[i])
			grades[i].append(math[i])
		self.radix(grades, 2, 1)
		self.radix(grades, 1, 1)
		self.radix(grades, 0, 0)
		for i in range(N):
			phy[i] = grades[i][0]
			chem[i] = grades[i][1]
			math[i] = grades[i][2]


class Solution:

	def customSort(self, phy, chem, math, N):
		d = {}
		for i in range(N):
			if phy[i] in d.keys():
				if chem[i] in d[phy[i]].keys():
					d[phy[i]][chem[i]].append(math[i])
				else:
					d[phy[i]][chem[i]] = [math[i]]
			else:
				d[phy[i]] = {chem[i]: [math[i]]}
		d = sorted(d.items())
		for i in range(len(d)):
			d[i] = list(d[i])
			d[i][1] = sorted(d[i][1].items(), reverse=True)
			for k in range(len(d[i][1])):
				d[i][1][k] = list(d[i][1][k])
				d[i][1][k][1] = sorted(d[i][1][k][1])
		z = 0
		for i in range(len(d)):
			for j in range(len(d[i][1])):
				for k in range(len(d[i][1][j][1])):
					phy[z] = d[i][0]
					chem[z] = d[i][1][j][0]
					math[z] = d[i][1][j][1][k]
					z += 1


class Solution:

	def customSort(self, phy, chem, math, N):
		marks = list(zip(phy, chem, math))
		marks.sort(key=lambda x: x[2])
		marks.sort(key=lambda x: -x[1])
		marks.sort(key=lambda x: x[0])
		for i in range(N):
			(phy[i], chem[i], math[i]) = marks[i]


class Solution:

	def customSort(self, phy, chem, math, N):
		arr = []
		for i in range(N):
			arr.append([])
		for i in range(N):
			arr[i].append(phy[i])
			arr[i].append(chem[i])
			arr[i].append(math[i])
		arr.sort(key=lambda x: x[2])
		arr.sort(key=lambda x: x[1], reverse=True)
		arr.sort(key=lambda x: x[0])
		for i in range(N):
			phy[i] = arr[i][0]
			chem[i] = arr[i][1]
			math[i] = arr[i][2]


from functools import cmp_to_key

class Solution:

	def customSort(self, phy, chem, math, N):

		def compare(num1, num2):
			if num1[0] == num2[0]:
				if num1[1] == num2[1]:
					if num1[2] == num2[2]:
						return 0
					elif num1[2] < num2[2]:
						return -1
					else:
						return 1
				elif num1[1] > num2[1]:
					return -1
				else:
					return 1
			elif num1[0] < num2[0]:
				return -1
			else:
				return 1
		arr = sorted(zip(phy, chem, math), key=cmp_to_key(compare))
		for i in range(N):
			phy[i] = arr[i][0]
			chem[i] = arr[i][1]
			math[i] = arr[i][2]