leetcode-study

289. Game of Life

class Solution:
    def gameOfLife(self, board: List[List[int]]) -> None:
        """
        Update the board to its next state according to the Game of Life rules.
        
        Each cell in the board is either live (1) or dead (0). The next state of each cell 
        is determined by its eight neighbors. The update is done in-place by encoding both 
        the original and new state in the same cell using bit manipulation.
        
        Parameters:
            board (List[List[int]]): A 2D list representing the current board state where
                                     each cell is 0 (dead) or 1 (live).
                                     
        The function updates the board in-place and does not return any value.
        """
        if not board or not board[0]:
            return

        m, n = len(board), len(board[0])
        
        # Iterate through each cell to compute the next state.
        # The least significant bit (LSB) holds the current state.
        # The second bit will hold the new state after the update.
        for i in range(m):
            for j in range(n):
                live_neighbors = 0  # Count of live neighbors for board[i][j]
                
                # Check all possible neighbors within bounds.
                for x in range(max(i - 1, 0), min(i + 2, m)):
                    for y in range(max(j - 1, 0), min(j + 2, n)):
                        live_neighbors += board[x][y] & 1  # Only count the original state.
                
                # Exclude the current cell from its neighbor count.
                live_neighbors -= board[i][j] & 1

                # Apply the Game of Life rules:
                # Rule 1 & 3: A live cell dies if it has fewer than 2 or more than 3 live neighbors.
                # Rule 2: A live cell lives on if it has 2 or 3 live neighbors.
                # Rule 4: A dead cell becomes live if it has exactly 3 live neighbors.
                if (board[i][j] & 1 and live_neighbors in (2, 3)) or (board[i][j] == 0 and live_neighbors == 3):
                    board[i][j] |= 2  # Set the 2nd bit to mark the cell as live in the next state
        
        # Update the board to the new state by shifting right to discard the old state.
        for i in range(m):
            for j in range(n):
                board[i][j] >>= 1  # New state is now in the least significant bit.

Summary of Techniques and Approaches: