Implement an Integer Spreadsheet with Formulas
HarveySoftware Engineer · Technical ScreenLast updated
Design an in-memory integer spreadsheet supporting cell assignments, additive formulas with nested references, and dynamic recalculation of acyclic dependency chains.
Problem Statement
Implement an in-memory integer spreadsheet engine that supports literal values, additive formulas referencing other cells, replacement updates, and evaluation of dependent cells.
Your Spreadsheet class should support the following operations:
set_cell(cell: str, expr: str) -> None: Sets the contents of the givencell. The expressionexprcan be:- An integer literal (e.g.,
"42","-5"). - An additive formula starting with
"="followed by terms separated by"+"(e.g.,"=A1+B2+10"). Each term in the formula is either a cell reference (e.g.,"A1") or an integer literal. - Overwriting an existing cell replaces its previous definition completely.
- An integer literal (e.g.,
get_value(cell: str) -> int: Computes and returns the current integer value of the cell.- If the cell has not been explicitly set, its value defaults to
0. - Any unset cell referenced within a formula also evaluates to
0. - All formulas are guaranteed to be acyclic (no circular dependencies).
- If the cell has not been explicitly set, its value defaults to
Interface
class Spreadsheet:
def __init__(self):
pass
def set_cell(self, cell: str, expr: str) -> None:
pass
def get_value(self, cell: str) -> int:
pass
Examples
Example 1
sheet = Spreadsheet()
sheet.set_cell("A1", "10")
sheet.set_cell("A2", "20")
sheet.set_cell("B1", "=A1+A2+5")
print(sheet.get_value("B1")) # Output: 35 (10 + 20 + 5)
print(sheet.get_value("C1")) # Output: 0 (unset cell defaults to 0)
# Updating a cell dynamically reflects in dependent cells
sheet.set_cell("A1", "5")
print(sheet.get_value("B1")) # Output: 30 (5 + 20 + 5)
Example 2
sheet = Spreadsheet()
sheet.set_cell("A1", "=B1+5")
print(sheet.get_value("A1")) # Output: 5 (B1 is unset, so it evaluates to 0)
sheet.set_cell("B1", "15")
print(sheet.get_value("A1")) # Output: 20 (B1 is now 15)
# Replacing formula with a literal
sheet.set_cell("A1", "100")
print(sheet.get_value("A1")) # Output: 100
Constraints
cellcoordinates consist of 1–3 uppercase letters followed by 1–4 digits (e.g.,"A1","BC102").- Integer literals in inputs fit within standard 32-bit signed integers.
- Formula chains are strictly acyclic and can reach up to
1,000cells deep. - Up to
10,000total calls toset_cellandget_value.
Hints
Hint 1
Store expressions in their raw or parsed form in a hash map, and consider whether to evaluate lazily upon get_value or eagerly upon set_cell.
Hint 2
Since dependency chains can be up to 1,000 cells deep, a recursive DFS for evaluation must be careful with Python's default recursion limit or be implemented iteratively / with memoization during a single get_value call.
Hint 3
If updating frequently but reading occasionally, lazy evaluation with per-call memoization is often simpler and avoids maintaining complex reverse dependency graphs.
Follow-up questions
- How would you detect and handle circular dependencies (cycles) if the acyclic guarantee were removed?
- If reads vastly outnumber writes, how would you design an eager caching system with cache invalidation across the dependency graph?
- How would you extend the expression parser to support full arithmetic operators (+, -, *, /) and parentheses while maintaining correct operator precedence?
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.