In-Memory Spreadsheet with Formulas, Cycle Detection and Read vs Write Computation

Read the full interview experience this question came from →

Quick Overview

Implement a simplified in-memory spreadsheet in Python with set_cell, set_formula and get_cell, where formulas use the four arithmetic operators and may reference other formula cells. Follow-ups test circular-reference detection, legal repeated references, and the trade-offs of computing values on read versus on write, including caching and invalidation.

In-Memory Spreadsheet with Formulas, Cycle Detection and Read vs Write Computation

Company: Citadel

Role: Software Engineer

Category: Software Engineering Fundamentals

Difficulty: medium

Interview Round: Technical Screen

Implement a simplified in-memory spreadsheet in Python that supports three operations: - `set_cell(cell, value)`: set the cell to a numeric value. - `set_formula(cell, formula)`: set the cell to a formula that supports addition, subtraction, multiplication and division. - `get_cell(cell)`: return the cell's current computed value. The follow-ups extend it to nested formulas, circular references and legal repeated references, and then turn to complexity and design trade-offs. ```text set_cell("A1", 5) set_cell("A2", 3) set_formula("B1", "A1 + A2") set_formula("C1", "B1 * 2") # nested: C1 reads a formula cell get_cell("C1") -> 16 set_cell("A1", 10) get_cell("C1") -> 26 set_formula("A1", "C1 - 1") get_cell("A1") -> error: circular reference A1 -> C1 -> B1 -> A1 ``` The example assumes formulas are strings of cell names, numbers and the four operators. A design that checks formulas when they are written may reject the last `set_formula` call itself instead. ### Clarifying Questions - What does a formula look like: a string such as `"A1 + B2 * 3"` that must be parsed with operator precedence and parentheses, or an already-parsed structure? Can it contain numeric literals? - What does a reference to a cell that was never set evaluate to: zero, or an error? - How should division by zero be reported? - Should a circular reference be rejected when the formula is set, or reported when a cell is read? - Does `set_cell` on a cell that holds a formula replace the formula, and the other way round? ### Part 1 — The three operations Implement `set_cell`, `set_formula` and `get_cell` for formulas whose operands are numbers and cells that hold numeric values. ```hint Two kinds of cell Decide what a cell stores when it holds a number and when it holds a formula, and what `get_cell` has to do differently for each. ``` #### What This Part Should Cover - A cell model and the three methods, with defined behavior for unset cells and for overwriting a cell - Formula evaluation with correct precedence for the four operators, or an explicitly stated formula format - Deliberate handling of division by zero and malformed formulas, with no use of `eval` on user input ### Part 2 — Nested formulas, circular references and repeated references Formulas may now reference cells that are themselves formulas, to any depth. Detect circular references and raise an error, both a direct self-reference (`A1 = A1 + 1`) and an indirect cycle such as A1 → B1 → C1 → A1. References that repeat without forming a cycle must keep working: a formula that names the same cell twice, or two cells that both read a shared cell. ```hint A shape that is not a cycle Trace a diamond: B1 and C1 both read A1, and D1 reads B1 and C1. Make sure your cycle check does not flag it, and count how many times A1 gets evaluated. ``` #### What This Part Should Cover - Evaluation of nested formulas to any depth - Cycle detection that catches self-references and indirect cycles and reports the cycle - No false positives on repeated or shared references, and no repeated evaluation of shared cells within one read - A consistent state after an error ### Part 3 — Complexity and design trade-offs Analyze the complexity of your design. Why compute the value in `get_cell`? Could the computation move into the set operations instead? If writes are rare and reads are frequent, which design fits better, and what does it need? ```hint Who has to hear about a change If values are computed when they are written, work out which other cells become wrong when one cell changes, and how you would find them quickly. ``` #### What This Part Should Cover - The cost of reads and writes in each design, in terms of the cells and references involved - Memoization within a single read versus a cache that persists across reads - Reverse dependencies and cache invalidation when a value or formula changes, including a formula overwritten with different references - A choice justified by the read/write ratio ### What a Strong Answer Covers - Clarifies the formula format, unset cells, division by zero and when cycles are reported - Working, tested code for the three operations and for nested formulas - Correct cycle detection with no false positives on repeated references - A concrete design discussion: read/write ratio, per-read memoization, a persistent cache, reverse dependencies, invalidation, and updating dependency edges when a formula is overwritten - The complexity of every operation in each design ### Follow-up Questions - One cell is read in a tight loop while its inputs change once a minute. How does each design behave? - Changing one input invalidates a long chain of dependents. How do you recompute them in a valid order, and each only once? - Add a function such as a sum over a range of cells (`A1:A100`). What changes in parsing and in dependency tracking? - How would you make the spreadsheet safe for concurrent readers and writers?

Overview: Implement a simplified in-memory spreadsheet in Python with set_cell, set_formula and get_cell, where formulas use the four arithmetic operators and may reference other formula cells. Follow-ups test circular-reference detection, legal repeated references, and the trade-offs of computing values on read versus on write, including caching and invalidation.

Read the full Citadel Software Engineer interview experience this question came from

Citadel logo
Citadel
Aug 12, 2026
mediumSoftware EngineerTechnical ScreenSoftware Engineering Fundamentals
2
0

Implement a simplified in-memory spreadsheet in Python that supports three operations:

  • set_cell(cell, value) : set the cell to a numeric value.
  • set_formula(cell, formula) : set the cell to a formula that supports addition, subtraction, multiplication and division.
  • get_cell(cell) : return the cell's current computed value.

The follow-ups extend it to nested formulas, circular references and legal repeated references, and then turn to complexity and design trade-offs.

set_cell("A1", 5)
set_cell("A2", 3)
set_formula("B1", "A1 + A2")
set_formula("C1", "B1 * 2")        # nested: C1 reads a formula cell
get_cell("C1")                     -> 16
set_cell("A1", 10)
get_cell("C1")                     -> 26
set_formula("A1", "C1 - 1")
get_cell("A1")                     -> error: circular reference A1 -> C1 -> B1 -> A1

The example assumes formulas are strings of cell names, numbers and the four operators. A design that checks formulas when they are written may reject the last set_formula call itself instead.

Clarifying Questions Guidance

  • What does a formula look like: a string such as "A1 + B2 * 3" that must be parsed with operator precedence and parentheses, or an already-parsed structure? Can it contain numeric literals?
  • What does a reference to a cell that was never set evaluate to: zero, or an error?
  • How should division by zero be reported?
  • Should a circular reference be rejected when the formula is set, or reported when a cell is read?
  • Does set_cell on a cell that holds a formula replace the formula, and the other way round?

Part 1 — The three operations

Implement set_cell, set_formula and get_cell for formulas whose operands are numbers and cells that hold numeric values.

What This Part Should Cover Guidance

  • A cell model and the three methods, with defined behavior for unset cells and for overwriting a cell
  • Formula evaluation with correct precedence for the four operators, or an explicitly stated formula format
  • Deliberate handling of division by zero and malformed formulas, with no use of eval on user input

Part 2 — Nested formulas, circular references and repeated references

Formulas may now reference cells that are themselves formulas, to any depth. Detect circular references and raise an error, both a direct self-reference (A1 = A1 + 1) and an indirect cycle such as A1 → B1 → C1 → A1. References that repeat without forming a cycle must keep working: a formula that names the same cell twice, or two cells that both read a shared cell.

What This Part Should Cover Guidance

  • Evaluation of nested formulas to any depth
  • Cycle detection that catches self-references and indirect cycles and reports the cycle
  • No false positives on repeated or shared references, and no repeated evaluation of shared cells within one read
  • A consistent state after an error

Part 3 — Complexity and design trade-offs

Analyze the complexity of your design. Why compute the value in get_cell? Could the computation move into the set operations instead? If writes are rare and reads are frequent, which design fits better, and what does it need?

What This Part Should Cover Guidance

  • The cost of reads and writes in each design, in terms of the cells and references involved
  • Memoization within a single read versus a cache that persists across reads
  • Reverse dependencies and cache invalidation when a value or formula changes, including a formula overwritten with different references
  • A choice justified by the read/write ratio

What a Strong Answer Covers Guidance

  • Clarifies the formula format, unset cells, division by zero and when cycles are reported
  • Working, tested code for the three operations and for nested formulas
  • Correct cycle detection with no false positives on repeated references
  • A concrete design discussion: read/write ratio, per-read memoization, a persistent cache, reverse dependencies, invalidation, and updating dependency edges when a formula is overwritten
  • The complexity of every operation in each design

Follow-up Questions Guidance

  • One cell is read in a tight loop while its inputs change once a minute. How does each design behave?
  • Changing one input invalidates a long chain of dependents. How do you recompute them in a valid order, and each only once?
  • Add a function such as a sum over a range of cells ( A1:A100 ). What changes in parsing and in dependency tracking?
  • How would you make the spreadsheet safe for concurrent readers and writers?