When we have a 2x2 square matrix we may have up to 24 different ones changing the positions of the elements.

We show some of them
```
a  b   a  b    a  c    a  c   a  d    a  d    b  a    b  a
c  d   d  c    d  b    b  d   b  c    c  b    c  d    d  c
```
You may think to generate the remaining ones until completing the set of 24 matrices.

Given a certain matrix of numbers, that may be repeated or not, calculate the total number of possible matrices that may be generated, changing the position of the elements.

E.g:
Case one
```
A = [[1,2,3],
     [3,4,5]]   #a 2x3 rectangle matrix with number 3 twice
```     
generates a set of ```360``` different matrices

Case two
```
A = [[1,1,1], 
     [2,2,3], 
     [3,3,3]]
```
generates a set of ```1260``` different matrices.

Case three
```
A = [[1,2,3],
     [4,5,6],
     [7,8,9]]
```     
generates a set of ```362880``` different matrices

This kata is not meant to apply a brute force algorithm to try to count the total amount of marices.

Features of The Random Tests
``` 
number of tests = 100
2 ≤ m ≤ 9
2 ≤ n ≤ 9
``` 
Enjoy it!

Available only in Python 2, Javascript and Ruby by the moment.

Source: codewars | Difficulty: EASY
Tags: Matrices

Fundamentals

Combinatorics

Data structures

Starter code: def count_perms(matrix):
	

Solutions:
from collections import Counter
from math import factorial

def count_perms(matrix):
	(m, n) = (len(matrix), len(matrix[0]))
	c = Counter([x for row in matrix for x in row])
	factors = []
	for (x, count) in c.most_common():
		if count > 1:
			factors.append(factorial(count))
	return factorial(m * n) / reduce(lambda a, b: a * b, factors, 1)


from math import factorial as fact
from functools import reduce
from collections import Counter

def count_perms(matrix):
	m = [elt for line in matrix for elt in line]
	return fact(len(m)) / reduce(lambda a, b: a * b, map(fact, Counter(m).values()), 1)


from collections import Counter
from itertools import chain, imap
from math import factorial
from operator import floordiv

def count_perms(matrix):
	xs = list(chain.from_iterable(matrix))
	return reduce(floordiv, imap(factorial, Counter(xs).itervalues()), factorial(len(xs)))


from collections import Counter
from functools import reduce
from math import factorial
from operator import mul

def count_perms(matrix):
	return factorial(len(matrix) * len(matrix[0])) // reduce(mul, map(factorial, Counter(sum(matrix, [])).values()))


from math import factorial as f
from functools import reduce
from collections import Counter
from operator import mul

def count_perms(m):
	m = sum(m, [])
	return f(len(m)) / reduce(mul, map(f, Counter(m).values()))


from collections import Counter
from itertools import chain
from operator import mul
from math import factorial

def count_perms(matrix):
	n = len(matrix) * len(matrix[0])
	c = Counter(chain.from_iterable(matrix))
	return factorial(n) / reduce(mul, map(factorial, c.itervalues()))


from math import factorial
from collections import Counter
from functools import reduce

def count_perms(matrix):
	items = [a for b in matrix for a in b]
	return factorial(len(items)) // reduce(lambda x, y: x * y, list(map(factorial, list(Counter(items).values()))), 1)


import math

def count_perms(matrix):
	freq = dict()
	for sub_matrix in matrix:
		for elem in sub_matrix:
			if freq.get(elem) is not None:
				freq[elem] = freq[elem] + 1
			else:
				freq[elem] = 1
	denominator = 1
	for frequency in freq.values():
		denominator = denominator * math.factorial(frequency)
	return math.factorial(sum(freq.values())) / denominator


from math import factorial as f
from operator import mul

def count_perms(m):
	rep = [[i for s in m for i in s].count(j) for j in set([i for s in m for i in s])]
	rep = [f(i) for i in rep]
	tot = len(m) * len(m[0])
	return f(tot) / reduce(mul, rep, 1)


(f, count_perms) = (lambda n: n < 1 or n * f(n - 1), lambda m: (lambda l: reduce(lambda x, y: x / f(l.count(y)), set(l), f(len(l))))(sum(m, [])))