In this kata, we will check is an array is (hyper)rectangular.  
A rectangular array is an N-dimensional array with fixed sized within one dimension. Its sizes can be repsented like A1xA2xA3...xAN. That means a N-dimensional array has N sizes. The 'As' are the hyperrectangular properties of an array.

You should implement a functions that returns a N-tuple with the arrays hyperrectangular properties or None if the array is not hyperrectangular.
```
hyperrectangularity_properties(arr)
```
## Note
An empty array IS rectagular and has one dimension of length 0
```
hyperrectangularity_properties([]) == (0,)
```
## Example
```
1D array
hyperrectangularity_properties([1,2,3]) == (3,)

2D arrays  

hyperrectangularity_properties(
                                [[0,1,2],
                                 [3,4,5],           
                                 [6,7,8]] ) == (3,3)                              
hyperrectangularity_properties(
                                [[0,1,2],
                                 [3,4,5]] ) == (2,3)
hyperrectangularity_properties( 
                                [[0,1,2],
                                 [3,4]  ] ) == None
3D arrays  
hyperrectangularity_properties(  
                                [
                                 [ [0], [2] ],
                                 [ [0], [2] ],  
                                 [ [0], [2] ]
                                              ] ) == (3,2,1)    
hyperrectangularity_properties(  
                                [
                                   [[0],[2]],
                                   [[0],[2,2]],   
                                   [[0],[2]]
                                              ] )  ==  None 
hyperrectangularity_properties(
                                [[ [], [], [] ]]
                                                ) ==  (1,3,0) 
```
### Heterogeneous Arrays can appear too
```
hyperrectangularity_properties(      
                                [[0,1,2],
                                 3,   
                                 [[4],5,6]] ) ==  None
hyperrectangularity_properties(      
                                [1,
                                 [1,2],   
                                 [[3],[4,[5]],[6]]
                                                  ] ) ==  None
                                                  hyperrectangularity_properties(
                                [[ [], [] ], [] ]
                                                  ) ==  None
hyperrectangularity_properties(
                                [ 1, [], [2, [3]] ]
                                                  ) ==  None
```
The first property shows the length of the outer layer. The second of the layer one step deeper and so on. The function should handle higher dimensions too.


## Input
##### N-dimensional array of integers

## Expected Ouput
##### An N-tuple with the hyperrectangularity properties

Source: codewars | Difficulty: EASY
Tags: Data structures

Mathematics

Complete search

Starter code: def hyperrectangularity_properties(arr):
	

Solutions:
from itertools import chain

def hyperrectangularity_properties(arr):
	(hr, arr) = ([], [arr])
	while 1:
		check = sum((isinstance(v, int) for v in arr))
		if check or not arr:
			if check == len(arr):
				return tuple(hr)
			break
		l = set(map(len, arr))
		if len(l) > 1:
			break
		hr.append(l.pop())
		arr = list(chain.from_iterable(arr))


import numpy as np

def hyperrectangularity_properties(arr):
	try:
		return np.shape(arr) if np.array(arr).dtype.char != 'O' else None
	except ValueError:
		return None


def hp(arr):
	if not isinstance(arr, list):
		return ()
	elif not arr:
		return (0,)
	xs = list(map(hp, arr))
	if None not in xs and all((x == xs[0] for x in xs)):
		return (len(arr),) + xs[0]
hyperrectangularity_properties = hp


hyperrectangularity_properties = h = lambda a: () if [] != a * 0 else (lambda f, *s: None if f == None or s else (len(a),) + f)(*(set(map(h, a)) or {()}))


def hyperrectangularity_properties(arr, d=[]):

	def get(arr, d):
		d.append(len(arr))
		if all((isinstance(i, int) for i in arr)):
			return tuple(d)
		else:
			le = len(arr[0]) if isinstance(arr[0], list) else 0
			if not all((isinstance(i, list) and len(i) == le for i in arr)):
				return
		if get(arr[0], d):
			return tuple(d)
	return get(arr, [])


def hyperrectangularity_properties(arr):
	v = len(arr)
	k = (v,)
	if not v:
		return k
	if len(set(map(type, arr))) != 1:
		return None
	if isinstance(arr[0], int):
		return k
	rest = list(set(map(hyperrectangularity_properties, arr)))
	if len(rest) == 1 and rest[0] != None:
		return k + rest[0]
	return None


def hyperrectangularity_properties(r):
	z = [len(r)]
	while len(r):
		if len(set((type(v) for v in r))) == 1:
			if type(r[0]) == list:
				if len(set((len(rr) for rr in r))) != 1:
					return None
				z.append(len(r[0]))
				r = [v for rr in r for v in rr]
			else:
				break
		else:
			return None
	return tuple(z)


def rec(arr):
	type = [isinstance(x, int) for x in arr]
	if len(set(type)) > 1:
		return None
	if not type or type[0]:
		return []
	size = list(map(len, arr))
	if len(set(size)) != 1:
		return None
	res = [rec(x) for x in arr]
	if None in res:
		return None
	if len(set(map(tuple, res))) != 1:
		return None
	return [size[0]] + res[0]

def hyperrectangularity_properties(arr):
	res = rec(arr)
	if res is None:
		return None
	return tuple([len(arr)] + res)