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

Difficulty: introductory

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)        # Check homogeneity
        if check or not arr:                                # some int are present or empty array (edge case)
            if check == len(arr): return tuple(hr)          # only int: found the bottom of the tree
            break
            
        l = set(map(len,arr))
        if len(l) > 1: break                                # invalid if different length found
        hr.append(l.pop())
        arr = list(chain.from_iterable(arr))                # get the "lower level"

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*0else(lambda f,*s:None if f==None or s else(len(a),)+f)(*set(map(h,a))or{()})

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

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


import numpy as np

def hyperrectangularity_properties(arr):
    try:
        return None if np.array(arr).dtype == np.dtype("O") else np.shape(arr)
    except (ValueError):
        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)

# This is a shit code, just little correction after little correction until I'm not even sure how it works
# There are probably edges cases to make it not work but hey, it passes the tests
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)