Implement spreadsheet cells with formulas
Company: Fuse Energy
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates proficiency in data structures and algorithms for dependency management, reactive computation, cycle detection, and state versioning (undo), assessing the ability to reason about how cells, formulas, and ranges interact under updates.
Constraints
- 0 <= len(operations) <= 2000
- Cell names contain uppercase letters followed by a positive row number, such as "A1" or "AA27"
- Set values are integers in the range [-10^9, 10^9]
- The total number of cells expanded from all ranges across all Sum operations is at most 200000
- All input operations are syntactically valid
Examples
Input: ([] ,)
Expected Output: []
Explanation: No operations produce no observable output.
Input: ([["Get", "Z99"], ["Undo"], ["Get", "A1"]],)
Expected Output: ["0", "0"]
Explanation: Unassigned cells read as 0. Undo with no successful writes is a no-op.
Input: ([["Set", "A1", "1"], ["Set", "B2", "2"], ["Sum", "D1", "A1:B2", "B2"], ["Get", "D1"], ["Set", "A1", "2"], ["Get", "D1"]],)
Expected Output: ["5", "6"]
Explanation: A1:B2 contributes A1 + A2 + B1 + B2, and B2 is referenced again. Initially the sum is 1 + 0 + 0 + 2 + 2 = 5. After A1 becomes 2, the reactive formula reads 6.
Input: ([["Set", "A1", "10"], ["Sum", "A1", "A1", "B1"], ["Get", "A1"], ["Get", "B1"]],)
Expected Output: ["ERROR", "10", "0"]
Explanation: The Sum would make A1 directly depend on itself, so it is rejected and A1 remains the literal value 10.
Input: ([["Sum", "A1", "B1"], ["Sum", "B1", "A1"], ["Get", "A1"], ["Get", "B1"], ["Set", "B1", "7"], ["Get", "A1"]],)
Expected Output: ["ERROR", "0", "0", "7"]
Explanation: A1 depending on B1 is valid. Making B1 depend on A1 would create the cycle B1 -> A1 -> B1, so it is rejected. Later setting B1 to 7 makes A1's formula evaluate to 7.
Input: ([["Set", "A1", "3"], ["Set", "B1", "4"], ["Sum", "C1", "A1", "B1"], ["Get", "C1"], ["Set", "A1", "10"], ["Get", "C1"], ["Undo"], ["Get", "C1"], ["Undo"], ["Get", "C1"], ["Undo"], ["Get", "B1"], ["Get", "A1"]],)
Expected Output: ["7", "14", "7", "0", "0", "3"]
Explanation: C1 is reactive. Undo first restores A1 from 10 to 3, then removes the formula from C1, then removes the literal assignment to B1.
Input: ([["Set", "A1", "-3"], ["Set", "A2", "5"], ["Sum", "B1", "A1:A2", "A1"], ["Get", "B1"]],)
Expected Output: ["-1"]
Explanation: The range A1:A2 contributes -3 + 5, and A1 is counted again, giving -3 + 5 - 3 = -1.
Input: ([["Set", "A1", "5"], ["Set", "B1", "2"], ["Sum", "A1", "B1"], ["Get", "A1"], ["Sum", "B1", "A1"], ["Undo"], ["Get", "A1"], ["Get", "B1"]],)
Expected Output: ["2", "ERROR", "5", "2"]
Explanation: A1 is replaced by a formula depending on B1. The attempted B1 formula would create a cycle, so it is rejected and not added to history. Undo therefore reverts the valid Sum on A1, restoring literal 5.
Hints
- Store formula dependencies as a graph from a formula cell to the cells it references. Keep reference counts because duplicates must contribute multiple times.
- To check whether assigning dest to depend on refs creates a cycle, ask whether any referenced cell can already reach dest through existing formula dependencies.