Quick Overview

Check four-in-a-row through the latest move using four axes, bounded bidirectional counts, edge handling, and constant work for a fixed target length.

Check Whether the Latest Move Creates Four in a Row

Company: Snowflake

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

Given a board, the current move's row and column, and its player, determine whether that move forms at least four consecutive pieces of that player horizontally, vertically, or along either diagonal. Implement `did_player_connect_four(board: int[][], row: int, col: int, player: int) -> bool`. ### Constraints & Assumptions - The board is rectangular with at least one row and column and at most 1000000 cells. Each cell is 0 (empty), 1, or 2. - Player is 1 or 2, the coordinates are valid, and the move has already been placed: `board[row][col] == player`. - A winning line must include the current move. An unrelated existing four-in-a-row elsewhere does not make this call true. - Runs longer than four also count. No gravity, turn legality, or full-game validation is required. - Four is a fixed target. Aim for O(1) time and O(1) extra space by checking only a bounded neighborhood of the current move. ### Examples ```text board = [[2,2,2,2]], row = 0, col = 3, player = 2 result = true ``` ```text board = [[1,1,1,1],[0,0,0,2]], row = 1, col = 3, player = 2 result = false ``` Explain how opposite directions combine around the current piece, how boundaries stop counting, and why no more than three cells per side are necessary for a fixed four-piece target. Include horizontal, vertical, both diagonals, split runs around the move, and edge/corner tests. Compare the cost if the target length were an input instead of fixed.

Overview: Check four-in-a-row through the latest move using four axes, bounded bidirectional counts, edge handling, and constant work for a fixed target length.

Read the full Snowflake Software Engineer interview experience this question came from

Given a board, the current move's row and column, and its player, determine whether that move forms at least four consecutive pieces of that player horizontally, vertically, or along either diagonal. Implement `did_player_connect_four(board: int[][], row: int, col: int, player: int) -> bool`. ### Constraints & Assumptions - The board is rectangular with at least one row and column and at most 1000000 cells. Each cell is 0 (empty), 1, or 2. - Player is 1 or 2, the coordinates are valid, and the move has already been placed: `board[row][col] == player`. - A winning line must include the current move. An unrelated existing four-in-a-row elsewhere does not make this call true. - Runs longer than four also count. No gravity, turn legality, or full-game validation is required. - Four is a fixed target. Aim for O(1) time and O(1) extra space by checking only a bounded neighborhood of the current move. ### Examples ```text board = [[2,2,2,2]], row = 0, col = 3, player = 2 result = true ``` ```text board = [[1,1,1,1],[0,0,0,2]], row = 1, col = 3, player = 2 result = false ``` Explain how opposite directions combine around the current piece, how boundaries stop counting, and why no more than three cells per side are necessary for a fixed four-piece target. Include horizontal, vertical, both diagonals, split runs around the move, and edge/corner tests. Compare the cost if the target length were an input instead of fixed.

Constraints

  • Nonempty rectangular board with at most 1000000 cells; values are 0, 1 or 2.
  • Player is 1 or 2; valid coordinates contain the already-placed current player piece.
  • A winning horizontal, vertical or diagonal line must include the current move and have at least four consecutive matching pieces.
  • Longer runs count; unrelated wins, gravity and full-game legality are outside this check.
  • Four is a fixed target, allowing a bounded neighborhood.

Examples

Input: ([[2, 2, 2, 2]], 0, 3, 2)

Expected Output: True

Explanation: A horizontal run can end at the move.

Input: ([[1, 1, 1, 1], [0, 0, 0, 2]], 1, 3, 2)

Expected Output: False

Explanation: An unrelated line does not make the move a winner.

Community answers

Answer by pjchen9413

def did_player_connect_four(board: list[list[int]], row: int, col: int, player: int) -> bool: m = len(board) n = len(board[0]) # Check horizontal, vertical, and both diagonals dirs = [(0, 1), (1, 0), (1, 1), (1, -1)] for dr, dc in dirs: consecutive_count = 1 # Count matching cells in one direction r = row + dr c = col + dc while 0 <= r < m and 0 <= c < n and board[r][c] == player: consecutive_count += 1 r += dr c += dc # Count matching cells in the opposite direction r = row - dr c = col - dc while 0 <= r < m and 0 <= c < n and board[r][c] == player: consecutive_count += 1 r -= dr c -= dc # Four or more consecutive cells means a win if consecutive_count >= 4: return True return False

Loading coding console...

Show the approach

Approach

Consider horizontal, vertical and the two diagonals as four axes. For each axis count the current piece once, then count consecutive matching pieces in each opposite direction, stopping at a boundary or a different cell. A line through the move is precisely the contiguous left segment, current piece and contiguous right segment, so summing both sides detects split runs. Inspecting at most three cells per side is enough: any four-piece line through the move uses at most three others on either side, and a side already reaching three establishes a win. Longer runs remain accepted. The algorithm checks at most 24 neighboring cells across four axes and uses constant traversal state, regardless of board size. Unrelated runs are never visited. For a variable target K, checking up to K-1 cells per side would take O(K) time and O(1) traversal space. C++ uses a const reference parameter to avoid copying the board and preserve the intended O(1) function cost.

Time complexity:
O(1) for the fixed target of four
Space complexity:
O(1)