Connect-N on an Infinite Board with Gravity
Company: Jane Street
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates implementation skills for efficient algorithms and data structures to manage a sparse, unbounded grid with gravity and to detect N-in-a-row runs both vertically and horizontally.
Constraints
- 2 <= n <= 1000
- 1 <= number of moves m <= 1e5
- -1e9 <= col <= 1e9 (negative columns are valid)
- 1 <= player <= 1e9
- The board is unbounded horizontally and vertically; occupancy is sparse.
- Each move must be judged independently, even after a prior win.
- Per-move work must stay O(N); do not rescan the whole board.
Examples
Input: (3, [[0,1],[1,2],[1,1],[2,2],[-1,1],[2,1],[-1,1]])
Expected Output: [False, False, False, False, False, False, False]
Explanation: Prompt example 1. Final board has player 1 at row 0 in columns -1 and 0, but column 1's row 0 holds player 2, so the horizontal run is only 2 (< 3). No column reaches 3 of the same player either — all moves report false.
Input: (3, [[0,1],[0,1],[5,2],[0,1],[5,2]])
Expected Output: [False, False, False, True, False]
Explanation: Prompt example 2. The fourth move stacks player 1's third consecutive piece in column 0 (rows 0,1,2), completing a vertical run of length 3 -> true. The other moves fall short.
Input: (2, [[-1,1],[0,1]])
Expected Output: [False, True]
Explanation: Horizontal win across a negative and a non-negative column: player 1 occupies row 0 of columns -1 and 0, a run of 2 for n=2.
Input: (3, [])
Expected Output: []
Explanation: Edge case: no moves means an empty result list.
Input: (5, [[0,1]])
Expected Output: [False]
Explanation: Single move can never reach a run of 5.
Input: (3, [[0,1],[1,2],[2,1],[3,1],[4,1]])
Expected Output: [False, False, False, False, True]
Explanation: Player 2's piece in column 1 blocks the horizontal run, so player 1's run is measured only from column 2 rightward. The fifth move makes columns 2,3,4 all player 1 at row 0 -> run of 3 -> true.
Input: (2, [[-1000000000,7],[-999999999,7]])
Expected Output: [False, True]
Explanation: Boundary columns at the extreme negative end (-1e9 and -1e9+1) form a horizontal run of 2 for player 7.
Hints
- Store each column as a stack (e.g. a dict from column index to a list of player IDs). The new piece's row is simply the current height of that column before insertion.
- The new piece is always on top of its column, so the only vertical run that can complete on this move ends at the new piece — count downward while the player matches; stop as soon as it differs.
- For the horizontal check, keep a separate map from (col, row) -> player. Only the new piece's row matters: walk left then right while the neighbor at the same row belongs to the same player. An empty cell (missing key) or an opponent's ID breaks the run.
- Because columns fill independently, adjacent columns can be at very different heights — never assume neighbors have a piece at your row; the (col, row) lookup naturally returns nothing for empty cells.