Spreadsheet Formulas with Dependency Updates
AmazonSoftware Engineer · OnsiteLast updated
Design a simplified in-memory spreadsheet supporting direct cell assignment, formula assignment (summation with potential duplicate cell references), and retrieval with dynamic dependency propagation.
Problem Statement
Design an in-memory spreadsheet system that supports setting cell values, defining summation formulas across multiple cells, and retrieving cell values. When a cell's value changes, any cell whose formula depends on it must reflect the updated value upon subsequent retrieval.
Implement the Spreadsheet class:
Spreadsheet(): Initializes the spreadsheet. All cells implicitly have a default value of0until explicitly set.set_val(cell: str, val: int) -> None: Assigns an integervaltocell. Ifcellpreviously held a formula, the formula and its dependencies are overwritten.set_sum(cell: str, formula_cells: list[str]) -> None: Setscellto evaluate to the sum of the values of the cells listed informula_cells. Note thatformula_cellsmay contain duplicate cell identifiers; each appearance contributes its value independently (e.g.,["A1", "A1"]computes2 * value("A1")). Overwrites any prior value or formula forcell.get(cell: str) -> int: Returns the current integer value ofcell.
You may assume that no operations will introduce circular dependencies.
Method Signatures
class Spreadsheet:
def __init__(self):
pass
def set_val(self, cell: str, val: int) -> None:
pass
def set_sum(self, cell: str, formula_cells: list[str]) -> None:
pass
def get(self, cell: str) -> int:
pass
Example
sheet = Spreadsheet()
sheet.set_val("A1", 10)
sheet.set_val("B1", 20)
sheet.set_sum("C1", ["A1", "B1", "A1"]) # C1 = 10 + 20 + 10 = 40
assert sheet.get("C1") == 40
sheet.set_val("A1", 5) # C1 should now be 5 + 20 + 5 = 30
assert sheet.get("C1") == 30
sheet.set_sum("D1", ["C1", "B1"]) # D1 = 30 + 20 = 50
assert sheet.get("D1") == 50
sheet.set_val("C1", 100) # C1 is now a static value, overwriting formula
assert sheet.get("D1") == 120 # D1 = 100 + 20 = 120
assert sheet.get("A1") == 5
Constraints
cellstrings consist of uppercase English letters followed by digits (e.g.,"A1","Z99").-10^6 <= val <= 10^61 <= len(formula_cells) <= 1000- At most
20,000total calls toset_val,set_sum, andgetcombined. - No cyclic dependencies will be introduced.
Edge Cases
- Referencing a cell in
formula_cellsthat has never been set should treat its value as0. - Overwriting a formula cell with a direct value must sever its old dependency graph edges so it no longer receives updates from previously referenced cells.
Hints
Hint 1
Model the spreadsheet as a directed acyclic graph (DAG) where directed edges point from a cell to the cells that depend on it.
Hint 2
Since duplicate references are allowed in `set_sum`, store cell dependencies with reference counts or multipliers rather than simple sets.
Hint 3
Decide between eager propagation (updating cached downstream values on write via BFS/DFS) and lazy evaluation with cache invalidation (marking downstream nodes dirty on write and recomputing on get).
Follow-up questions
- How would you detect and reject an operation that introduces a circular dependency before committing the change?
- If read operations (`get`) vastly outnumber write operations (`set_val`, `set_sum`), which evaluation strategy (eager push vs. lazy pull with dirty flags) minimizes overall latency?
- How would you extend this design to support range queries (e.g., `"A1:B10"`) efficiently without materializing individual edges for every cell in large ranges?
Solution walkthrough is for members
Get the full walkthrough with reference code and complexity analysis, plus Kitty Coach at 300 messages a day. Hints, the code runner and community answers stay free.