<p>You are given an <code>n x n</code> binary grid <code>board</code>. In each move, you can swap any two rows with each other, or any two columns with each other.</p>

<p>Return <em>the minimum number of moves to transform the board into a <strong>chessboard board</strong></em>. If the task is impossible, return <code>-1</code>.</p>

<p>A <strong>chessboard board</strong> is a board where no <code>0</code>&#39;s and no <code>1</code>&#39;s are 4-directionally adjacent.</p>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/06/29/chessboard1-grid.jpg" style="width: 500px; height: 145px;" />
<pre>
<strong>Input:</strong> board = [[0,1,1,0],[0,1,1,0],[1,0,0,1],[1,0,0,1]]
<strong>Output:</strong> 2
<strong>Explanation:</strong> One potential sequence of moves is shown.
The first move swaps the first and second column.
The second move swaps the second and third row.
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/06/29/chessboard2-grid.jpg" style="width: 164px; height: 165px;" />
<pre>
<strong>Input:</strong> board = [[0,1],[1,0]]
<strong>Output:</strong> 0
<strong>Explanation:</strong> Also note that the board with 0 in the top left corner, is also a valid chessboard.
</pre>

<p><strong class="example">Example 3:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2021/06/29/chessboard3-grid.jpg" style="width: 164px; height: 165px;" />
<pre>
<strong>Input:</strong> board = [[1,0],[1,0]]
<strong>Output:</strong> -1
<strong>Explanation:</strong> No matter what sequence of moves you make, you cannot end with a valid chessboard.
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>n == board.length</code></li>
	<li><code>n == board[i].length</code></li>
	<li><code>2 &lt;= n &lt;= 30</code></li>
	<li><code>board[i][j]</code> is either&nbsp;<code>0</code> or <code>1</code>.</li>
</ul>

class Solution:
    # check if there are two types of lines or that the sorted values are not the balanced form 
    # on fail, return -1 
    # on pass, return 1 
    def check_even(self, count) : 
        if len(count) != 2 or sorted(count.values()) != self.balanced : 
            return -1 
        return 1

    # check if all are alternating row by row 
    # if so, alternate is good, if not, not possible, return -1 
    def all_opposite(self, line1, line2) : 
        if not all (line1_value ^ line2_value for line1_value, line2_value in zip(line1, line2)) : 
            return -1 
        return 1 
    
    # set your sums of lists of values based on your current lists of values 
    def set_sums_of_lists_of_values(self) : 
        self.sums_of_lists_of_values = [sum(list_of_values) for list_of_values in self.lists_of_values]

    # update your number of swaps using your current sums of lists of values 
    def update_number_of_swaps(self) : 
        self.number_of_swaps += min(self.sums_of_lists_of_values) // 2

    def set_lists_of_values(self, line1) : 
        self.lists_of_values = []
        for start in self.starts : 
            new_list = []
            for index, value in enumerate(line1, start) : 
                new_list.append((index-value) % 2)
            self.lists_of_values.append(new_list)

    def set_starting_values(self, line1) : 
        self.starts = [+(line1.count(1) * 2 > self.n)] if self.n & 1 else [0, 1]

    def process_line(self, line1) : 
        # starts is the starting value of line 1 
        # starts gets added to an empty list the value of 
        # the number of 1s found multipled by 2 is greater than n if n is odd 
        # this is to deal with the one off 1 factor on odd boards alternating 
        # otherwise, it gets only 0 and 1 
        self.set_starting_values(line1)
        # use starts and line1 to build the list 
        self.set_lists_of_values(line1) 
        # use the lists of values to build the sums of lists of values 
        self.set_sums_of_lists_of_values()
        # use those to update the number of swaps 
        self.update_number_of_swaps()

    def process_board(self, board) : 
        # get the count as the pair of tuples of the board as frequencies with the zip of the rows 
        for count in (collections.Counter(map(tuple, board)), collections.Counter(zip(*board))) :  
            # if there are more than 2 kinds of lines or they are not balanced 
            if self.check_even(count) == -1 : 
                return -1 
            line1, line2 = count
            # if the values of the two lines when zipped are not always alternating, also false
            # this can be checked with exclusive or of the values in line1 and line 2 as l1v and l2v
            if self.all_opposite(line1, line2) == -1 : 
                return -1 
            # pass the line which is the first item in count 
            self.process_line(line1)
        # if you haven't returned yet, return now 
        return self.number_of_swaps

    def set_up_for_processing_board(self, n) : 
        # n by n board 
        self.n = n 
        # number of swaps needed 
        self.number_of_swaps = 0
        # balanced form for chess board 
        self.balanced = [n//2, (n+1)//2]
            
    def movesToChessboard(self, board: List[List[int]]) -> int:
        # set up for processing 
        self.set_up_for_processing_board(len(board))
        # then process it 
        return self.process_board(board)
16700