"""
Takuzu is a binary puzzle game.
The objective is to fill a nxn grid with 0s and 1s according to the following rules:
1. Each row and column must contain an equal number of 0s and 1s.
2. No more than two consecutive similar numbers are allowed.
3. Each pair of rows is different, and each pair of columns is different.
The game is won when the grid is filled according to the rules.
This class provides a method to check if a grid is valid.
"""

def check_is_square(grid: list[list[int]]) -> bool:
    """
    Checks if the grid is square, that is, it has the same number of rows and columns.
    :return: bool, True if the grid is square, False otherwise
    """
    return all(len(row) == len(grid) for row in grid)


def check_only_0s_and_1s(grid: list[list[int]]) -> bool:
    """
    Checks if the grid contains only 0s and 1s.
    :return: bool, True if the grid contains only 0s and 1s, False otherwise
    """
    return all(all(cell in [0, 1] for cell in row) for row in grid)


def check_number_of_0s_and_1s(seq: list[int]) -> bool:
    """
    Checks if the sequence satisfies the first rule of Takuzu,
    that is, each row and column must contain an equal number of 0s and 1s.
    :return: bool, True if the sequence satisfies the rule, False otherwise
    """
    return seq.count(0) == seq.count(1)


def check_no_more_than_two_similar_numbers_consecutive(seq: list[int]) -> bool:
    """
    Checks if the sequence satisfies the second rule of Takuzu,
    that is, no more than two consecutive similar numbers are allowed.
    :return: bool, True if the sequence satisfies the rule, False otherwise
    """
    return all(seq[i] != seq[i + 1] or seq[i] != seq[i + 2] for i in range(len(seq) - 2))


def check_uniqueness(seq1: list[int], seq2: list[int]) -> bool:
    """
    Checks if the third rule of Takuzu is satisfied,
    that is, each pair of rows (resp. columns) is different.
    :param seq1: list[int], the first sequence
    :param seq2: list[int], the second sequence
    :return: bool, True if the sequences are unique, False otherwise
    """
    return seq1 != seq2


def grid_checker(grid: list[list[int]]) -> bool:
    """
    Checks if the grid is valid according to the rules of 
    The three rules are:
    1. Each row and column must contain an equal number of 0s and 1s.
    2. No more than two similar numbers adjacent to each other are allowed.
    3. Each pair of rows is different, and each pair of columns is different.
    :param grid: list[list[int]], the grid to be checked
    :return: bool, True if the grid is valid, False otherwise
    """
    if not check_is_square(grid):
        return False
    if not check_only_0s_and_1s(grid):
        return False
    for row in grid:
        if not check_number_of_0s_and_1s(row):
            return False
        if not check_no_more_than_two_similar_numbers_consecutive(row):
            return False
    for col in range(len(grid)):
        if not check_number_of_0s_and_1s([grid[row][col] for row in range(len(grid))]):
            return False
        if not check_no_more_than_two_similar_numbers_consecutive(
                [grid[row][col] for row in range(len(grid))]):
            return False
    for i in range(len(grid)):
        for j in range(i + 1, len(grid)):
            if not check_uniqueness(grid[i], grid[j]):
                return False
            if not check_uniqueness([grid[row][i] for row in range(len(grid))],
                                            [grid[row][j] for row in range(len(grid))]):
                return False
    return True


if __name__ == '__main__':
    grid = [[0, 1, 1, 0], [1, 0, 0, 1], [0, 0, 1, 1], [1, 1, 0, 0]]
    print(grid_checker(grid))