Implement Ultimate Tic-Tac-Toe
Company: Hebbia
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates object-oriented design, state management, rule validation, and algorithmic reasoning for both standard and Ultimate Tic-Tac-Toe, testing competencies in data structures, winner-detection logic, and hierarchical game modeling.
Part 1: Standard Tic-Tac-Toe Move Simulator
Constraints
- 0 <= len(moves) <= 100000
- Board size is always 3x3
- Malformed move strings must be treated as invalid
- Do not enforce alternating turns; validate only against board state and the rules above
Examples
Input: []
Expected Output: ['', 'None', '...', '...', '...']
Explanation: Edge case: no moves, so the board stays empty and there is no winner.
Input: ['0,0,X']
Expected Output: ['1', 'None', 'X..', '...', '...']
Explanation: A single valid move places X in the top-left corner.
Input: ['0,0,X', '1,0,O', '0,1,X', '1,1,O', '0,2,X', '2,2,O']
Expected Output: ['111110', 'X', 'XXX', 'OO.', '...']
Explanation: X wins on the top row after the fifth move, so the sixth move is rejected.
Input: ['0,0,X', '0,0,O', '3,1,X', '1,1,Z', '1,1,O']
Expected Output: ['10001', 'None', 'X..', '.O.', '...']
Explanation: This includes an occupied cell, an out-of-bounds move, and an invalid player symbol.
Hints
- Use a 3x3 array of characters initialized with '.'.
- After each successful move, checking all 8 winning lines is still constant time.
Part 2: Ultimate Tic-Tac-Toe Move Simulator
Constraints
- 0 <= len(moves) <= 100000
- There are always exactly 9 small boards, each of size 3x3
- A move is invalid if it targets an out-of-bounds location, a non-playable small board, an occupied cell, an invalid player symbol, or the wrong forced board when one exists
- Once a small board is won, it is captured and cannot be played again
- Do not enforce alternating turns; validate only according to the game state and the rules above
Examples
Input: []
Expected Output: ['', 'None', '*', '.........', '.........', '.........', '.........', '.........', '.........', '.........', '.........', '.........']
Explanation: Edge case: an empty game has no winner, any playable board may be chosen next, and the 9x9 display is blank.
Input: ['0,0,1,2,X']
Expected Output: ['1', 'None', '1,2', '.........', '..X......', '.........', '.........', '.........', '.........', '.........', '.........', '.........']
Explanation: A single move in small board (0,0) at cell (1,2) forces the next player to small board (1,2).
Input: ['0,0,1,1,X', '0,0,0,0,O', '1,1,0,0,O']
Expected Output: ['101', 'None', '0,0', '.........', '.X.......', '.........', '...O.....', '.........', '.........', '.........', '.........', '.........']
Explanation: After the first valid move, the next move must be played in small board (1,1). The second move is rejected because it ignores that requirement. The third move is valid.
Input: ['1,1,0,0,X', '0,0,0,0,X', '0,0,0,1,X', '0,1,0,0,X', '0,0,0,2,X', '0,2,0,0,O']
Expected Output: ['111111', 'None', '*', 'XXXX..O..', '.........', '.........', '...X.....', '.........', '.........', '.........', '.........', '.........']
Explanation: The first five moves capture small board (0,0) for X. The last move sends the next player to (0,0), but that board is already won, so the next move may be made on any playable small board.
Input: ['1,1,0,0,X', '0,0,0,0,X', '0,0,0,1,X', '0,1,0,0,X', '0,0,0,2,X', '0,2,0,0,X', '1,1,0,1,X', '0,1,0,1,X', '0,1,0,2,X', '0,2,0,1,X', '1,2,0,2,X', '0,2,0,2,X']
Expected Output: ['111111111111', 'X', 'None', 'XXXXXXXXX', '.........', '.........', '...XX...X', '.........', '.........', '.........', '.........', '.........']
Explanation: X captures the three small boards across the top row of the large board, so X wins the overall game.
Hints
- Track two layers of state: the 9 small boards themselves and a separate 3x3 grid that stores which small boards have been captured.
- Keep a 'forced board' coordinate from the previous valid move. Only ignore it when that target small board is already full or captured.