Given a Sudoku data structure with size `NxN, N > 0 and √N == integer`, write a method to validate if it has been filled out correctly.


The data structure is a multi-dimensional Array, i.e:
```
[
  [7,8,4,  1,5,9,  3,2,6],
  [5,3,9,  6,7,2,  8,4,1],
  [6,1,2,  4,3,8,  7,5,9],
  
  [9,2,8,  7,1,5,  4,6,3],
  [3,5,7,  8,4,6,  1,9,2],
  [4,6,1,  9,2,3,  5,8,7],
  
  [8,7,6,  3,9,4,  2,1,5],
  [2,4,3,  5,6,1,  9,7,8],
  [1,9,5,  2,8,7,  6,3,4]
]
```

**Rules for validation**

- Data structure dimension: `NxN` where `N > 0` and `√N == integer`
- Rows may only contain integers: `1..N (N included)`
- Columns may only contain integers: `1..N (N included)`
- *'Little squares'* (`3x3` in example above) may also only contain integers: `1..N (N included)`

Difficulty: MEDIUM_HARD
Tags: Data structures

Ad-hoc
Skill types: Data structures

Starter code:
def __init__(self, board):
	

Solutions:
import math

class Sudoku(object):

	def __init__(self, board):
		self.board = board

	def is_valid(self):
		if not isinstance(self.board, list):
			return False
		n = len(self.board)
		rootN = int(round(math.sqrt(n)))
		if rootN * rootN != n:
			return False
		isValidRow = lambda r: isinstance(r, list) and len(r) == n and all([type(x) == int for x in r])
		if not all(map(isValidRow, self.board)):
			return False
		oneToN = set(range(1, n + 1))
		isOneToN = lambda l: set(l) == oneToN
		tranpose = [[self.board[j][i] for i in range(n)] for j in range(n)]
		squares = [[self.board[p + x][q + y] for x in range(rootN) for y in range(rootN)] for p in range(0, n, rootN) for q in range(0, n, rootN)]
		return all(map(isOneToN, self.board)) and all(map(isOneToN, tranpose)) and all(map(isOneToN, squares))


import numpy as np

class Sudoku(object):

	def __init__(self, theArray):
		self.grid = np.array(theArray)
		self.listgrid = theArray
		self.N = len(theArray)
		self.M = len(theArray[0])

	def has_valid_size(self):
		if isinstance(self.listgrid[0][0], bool):
			return False
		if self.grid.shape == (1, 1):
			return True
		for i in self.listgrid:
			if len(i) != self.N:
				return False
		return True

	def is_valid(self):
		if not self.has_valid_size():
			return False
		seqs2check = [self.getRowsIterator(), self.getColsIterator(), self.getSquaresIterator()]
		for it in seqs2check:
			for seq in it:
				if self.checkSeq(seq) == False:
					return False
		return True

	def getRowsIterator(self):
		for i in range(self.N):
			yield self.grid[i, :]

	def getColsIterator(self):
		for i in range(self.N):
			yield self.grid[:, i]

	def getSquaresIterator(self):
		squareSize = int(np.sqrt(self.N))
		for i in range(squareSize):
			for j in range(squareSize):
				ix1 = i * squareSize
				ix2 = j * squareSize
				yield self.grid[ix1:ix1 + squareSize, ix2:ix2 + squareSize].flatten()

	def checkSeq(self, seq):
		return sorted(seq) == list(range(1, self.N + 1))


import math

class Sudoku(object):

	def __init__(self, board):
		self.board = board
		self.size = len(board)

	@staticmethod
	def reduce_logic(seq):
		return reduce(lambda x, y: x and y, seq)

	def is_square(self):
		return self.reduce_logic(map(lambda x: len(x) == self.size, self.board))

	def check_number(self):
		return self.reduce_logic(map(lambda x: 0 < x <= self.size and type(x) == type(1), reduce(lambda x, y: x + y, self.board)))

	def check_seq(self, seq):
		return self.reduce_logic(map(lambda x: len(set(x)) == self.size, seq))

	def check_rows(self):
		return self.check_seq(self.board)

	def check_cols(self):
		cols = [map(lambda x: x[i], self.board) for i in range(self.size)]
		return self.check_seq(cols)

	def check_little_squares(self):
		sq = int(math.sqrt(self.size))
		squares = [reduce(lambda x, y: x + y, map(lambda x: x[i:i + sq], self.board[j:j + sq])) for j in range(0, self.size, sq) for i in range(0, self.size, sq)]
		return self.check_seq(squares)

	def is_valid(self):
		if self.is_square() and self.check_number() and self.check_rows() and self.check_cols() and self.check_little_squares():
			return True
		else:
			return False


from itertools import chain
import math

class Sudoku(object):

	def __init__(self, data):
		self.grip = data
		self.len = len(data)
		self.valid = self.len == 1 and data != [[1]] or not all((len(e) == self.len for e in data)) or all((type(x) != int for e in data for x in e))
		self.box = int(math.sqrt(self.len))

	def resp(self):
		self.grip = list(zip(*[list(zip(*[iter(e)] * self.box)) for e in self.grip][::-1]))
		return [list(chain(*list(zip(*[iter(e)] * self.box))[i])) for e in self.grip for i in range(len(self.grip) // self.box)]

	def is_valid(self):
		return not self.valid and all((len(set(e)) == self.len for e in self.resp()))


class Sudoku(object):

	def __init__(self, grid):
		self.grid = grid
		self.dim = len(grid)
		self.boxsize = int(self.dim ** 0.5)
		self.nums = set(range(1, self.dim + 1))

	def row_valid(self, row):
		return self.nums == set(self.grid[row])

	def col_valid(self, col):
		return self.nums == set((self.grid[row][col] for row in range(self.dim)))

	def box_valid(self, box):
		(box_row, box_col) = divmod(box, self.boxsize)
		(box_row, box_col) = (box_row * self.boxsize, box_col * self.boxsize)
		return self.nums == set((self.grid[row][col] for row in range(box_row, box_row + self.boxsize) for col in range(box_col, box_col + self.boxsize)))

	def is_valid(self):
		if any((len(row) != self.dim for row in self.grid)):
			return False
		if any((any((not isinstance(i, int) or i is True or i is False for i in row)) for row in self.grid)):
			return False
		return all((self.row_valid(row) for row in range(self.dim))) and all((self.col_valid(col) for col in range(self.dim))) and all((self.box_valid(box) for box in range(self.dim)))


class Sudoku(object):

	def __init__(self, board):
		self.board = board

	def is_valid(self):
		n = int(len(self.board) ** 0.5)
		if not all((len(row) == n * n and all((not isinstance(cell, bool) for cell in row)) for row in self.board)):
			return False
		(r, rr) = (range(n), range(0, n * n, n))
		blocks = [[self.board[x + a][y + b] for a in r for b in r] for x in rr for y in rr]
		return not [x for x in self.board + list(zip(*self.board)) + blocks if set(x) != set(range(1, n * n + 1))]


from itertools import chain

class Sudoku(object):

	def __init__(self, data):
		self.data = data
		self.n = len(data)
		self.nums = set(range(1, self.n + 1))

	def is_valid(self):
		return all((len(row) == self.n for row in self.data)) and self.are_all_ints() and self.are_row_nums_valid() and self.are_col_nums_valid() and self.are_squares_valid()

	def are_all_ints(self):
		return all((isinstance(x, int) and (not isinstance(x, bool)) for row in self.data for x in row))

	def are_row_nums_valid(self):
		return all((set(row) == self.nums for row in self.data))

	def are_col_nums_valid(self):
		return all((set(row) == self.nums for row in zip(*self.data)))

	def are_squares_valid(self):
		sq = int(self.n ** 0.5)
		return all((set(chain.from_iterable((row[j:j + sq] for row in self.data[i:i + sq]))) == self.nums for i in range(0, self.n, sq) for j in range(0, self.n, sq)))


import math

class Sudoku(object):

	def __init__(self, board):
		self.board = board
		self.size = len(board)
		self.lil_size = math.sqrt(self.size)

	def is_valid(self):
		if not all((len(r) == self.size for r in self.rows())):
			return False
		if not self.lil_size.is_integer():
			return False
		if self.board[0][0] is True:
			return False
		numbers = range(1, self.size + 1)
		groups = self.rows() + self.columns() + self.lil_squares()
		for group in groups:
			if sorted(group) != numbers:
				return False
		return True

	def rows(self):
		return self.board

	def columns(self):
		return zip(*self.rows())

	def lil_squares(self):
		result = []
		size = int(self.lil_size)
		for i in range(size):
			for j in range(size):
				square = []
				for k in range(size):
					for l in range(size):
						square.append(self.board[i * size + k][j * size + l])
				result.append(square)
		return result


from itertools import chain

class Sudoku(object):

	def __init__(self, grid):
		self.grid = grid
		self.size = len(grid)
		self.good_zone = set(range(1, self.size + 1))

	def __iter__(self):
		rows = self.grid
		cols = zip(*rows)
		square_size = int(self.size ** 0.5)
		squares = [sum((rows[y + i][x:x + square_size] for i in range(square_size)), []) for y in range(0, self.size, square_size) for x in range(0, self.size, square_size)]
		return chain(rows, cols, squares)

	def valid_data_types(self):
		return all((type(num) == int for num in chain(*self.grid)))

	def zone_is_valid(self, zone):
		return set(zone) == self.good_zone

	def is_valid(self):
		if not self.valid_data_types():
			return False
		return all((self.zone_is_valid(zone) for zone in self))