Simulate toppling board game outcome
Company: Chime
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: Medium
Interview Round: Onsite
Quick Answer: This question evaluates a candidate's ability to implement a discrete board-game simulation, including state management, turn-based ownership semantics, stack-based piece handling, capture mechanics, and game termination detection.
Constraints
- 3 <= n <= 9
- 0 <= len(moves) <= 100000
- Each move is either `pXY` or `tXYD`
- X and Y are digits in the range [0, n - 1]
- D is one of `u`, `r`, `d`, `l`
- All moves are valid and well formed
Examples
Input: (3, ["p10", "p12", "p10", "t10r"])
Expected Output: "player 1 is the winner"
Explanation: Player 1 builds a stack of 2 at (1,0), then topples right. One piece lands on (1,1), and the next lands on player 2's cell (1,2), capturing it. Player 2 is left with zero pieces.
Input: (3, ["p00", "p22", "p02", "p22", "t22u", "t02l"])
Expected Output: "player 2 is the winner"
Explanation: After `p22`, both `t22u` and `t02l` belong to player 2 because no new Place move occurs. Player 2 first captures (0,2), then topples it left to capture (0,0), eliminating player 1.
Input: (4, ["p00", "p11", "p00", "t00d"])
Expected Output: "in progress"
Explanation: Player 1 topples two pieces downward from (0,0) to (1,0) and (2,0), but player 2 still has a piece at (1,1). Both players still have pieces.
Input: (3, [])
Expected Output: "in progress"
Explanation: No moves have been played, so the game is still in progress.
Input: (3, ["p01", "p22", "p01", "t01u"])
Expected Output: "player 2 is the winner"
Explanation: Player 1 topples a stack of 2 upward from the top row, so both pieces fall off the board and are lost. Since both players had already placed at least once, player 1 is eliminated and player 2 wins.
Solution
def solution(n, moves):
owners = [[0] * n for _ in range(n)]
heights = [[0] * n for _ in range(n)]
# totals[player] = total number of pieces currently owned by that player
totals = [0, 0, 0]
placed_once = [False, False, False]
# The current player is the player who made the most recent Place move.
current_player = 0
place_count = 0
directions = {
'u': (-1, 0),
'r': (0, 1),
'd': (1, 0),
'l': (0, -1),
}
def check_winner():
if placed_once[1] and placed_once[2]:
if totals[1] == 0:
return "player 2 is the winner"
if totals[2] == 0:
return "player 1 is the winner"
return None
for move in moves:
if move[0] == 'p':
current_player = 1 if place_count % 2 == 0 else 2
place_count += 1
placed_once[current_player] = True
x = int(move[1])
y = int(move[2])
if owners[x][y] == 0:
owners[x][y] = current_player
heights[x][y] = 1
else:
heights[x][y] += 1
totals[current_player] += 1
else: # Topple
x = int(move[1])
y = int(move[2])
d = move[3]
dx, dy = directions[d]
stack_size = heights[x][y]
# Remove the source stack from the current player.
owners[x][y] = 0
heights[x][y] = 0
totals[current_player] -= stack_size
# Only cells until the board edge can receive pieces.
step = 1
while step <= stack_size:
nx = x + dx * step
ny = y + dy * step
if not (0 <= nx < n and 0 <= ny < n):
break
if owners[nx][ny] == 0:
owners[nx][ny] = current_player
heights[nx][ny] = 1
totals[current_player] += 1
elif owners[nx][ny] == current_player:
heights[nx][ny] += 1
totals[current_player] += 1
else:
other = owners[nx][ny]
captured_height = heights[nx][ny]
totals[other] -= captured_height
owners[nx][ny] = current_player
heights[nx][ny] = captured_height + 1
totals[current_player] += captured_height + 1
step += 1
result = check_winner()
if result is not None:
return result
return "in progress"Time complexity: O(len(moves) * n). Space complexity: O(n^2).
Hints
- Store each board cell as two pieces of information: owner and stack height. Also keep total piece counts for each player so you can detect a winner in O(1) after every move.
- During a topple, only the cells from the source to the board edge can receive pieces. Since `n <= 9`, at most `n - 1` dropped pieces stay on the board; the rest are immediately lost.