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