Eager Spreadsheet Formulas with Constant-Time Reads

Read the full interview experience this question came from →

Quick Overview

Implement eager spreadsheet formulas with constant-time cached reads, transitive dependency updates, cycle rejection, and atomic definition replacement.

Eager Spreadsheet Formulas with Constant-Time Reads

Company: Harvey

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Technical Screen

Implement a spreadsheet with `set_cell`, `get_cell`, arithmetic formulas, dependency updates, and circular-reference rejection. Each successful write must leave computed values ready so a subsequent `get_cell` is a constant-time cached read. Implement `eager_sheet(operations: string[][]) -> string[]`. Each row is `["set", cell, raw]` or `["get", cell]`. Return one string per operation: - A successful set returns `"OK"`. - A set that would introduce a circular reference returns `"CYCLE"` and leaves the previous sheet unchanged. - A get returns the cell's computed integer in canonical decimal notation, with no leading plus or leading zeros; zero is `"0"`. ### Formula and edit contract The source describes formulas and dependency/cycle handling but does not give a grammar. This practice version explicitly uses: - Cell names are uppercase letters followed by a positive decimal row number with no leading zeros, such as `A1` or `AA10`. - Raw values are signed integer strings or formulas beginning with `=`. - Formula grammar is `term (('+' | '-') term)*`, where a term is a nonnegative integer or a cell reference. Spaces may surround tokens. Unary signs and parentheses inside formulas are excluded. - Unset cells evaluate to zero. Repeated references contribute repeatedly, so `=A1+A1` counts the value twice. - Set replaces the entire previous definition, including its dependency links. It may change a literal to a formula or a formula to a literal. - Direct and indirect cycles are rejected before the edit becomes visible. A failed set preserves both the old definition and every previously computed value. - On a successful set, update every affected dependent value before processing the next operation. Implement get using stored results, without dependency traversal on reads. ### Constraints - There are at most 500 operations and at most 100 terms per formula. - All names and expressions are syntactically valid. - Numeric tokens, stored literals, and all intermediate arithmetic results for an acyclic prospective sheet fit in a signed 32-bit integer. - The sheet starts empty, and operations are processed sequentially. - Cycle-error serialization, unset-cell behavior, grammar, and bounds are explicit practice assumptions. The constant-time-read requirement and the need to consider write-versus-read evaluation come from the reported task. ### Examples ```text operations = [ ["set","A1","2"], ["set","B1","=A1+1"], ["set","C1","=A1+B1"], ["set","A1","5"], ["get","C1"] ] result = ["OK","OK","OK","OK","11"] ``` ```text operations = [ ["set","A1","=B1"], ["set","B1","=A1+1"], ["get","A1"], ["set","A1","3"], ["set","B1","=A1+1"], ["get","B1"] ] result = ["OK","CYCLE","0","OK","OK","4"] ``` The rejected edit in the second example leaves `B1` unset. Replacing `A1` with a literal later removes the dependency that would have completed the cycle. ```hint Keep both graph directions One graph direction identifies a formula's inputs. The other identifies which cached values can change after an input edit. Recompute dependents only after their changed inputs are ready. ```

Overview: Implement eager spreadsheet formulas with constant-time cached reads, transitive dependency updates, cycle rejection, and atomic definition replacement.

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

|Home/Coding & Algorithms/Harvey
Harvey logo
Harvey
Sep 1, 2026
mediumSoftware EngineerTechnical ScreenCoding & Algorithms
0
0

Implement a spreadsheet with set_cell, get_cell, arithmetic formulas, dependency updates, and circular-reference rejection. Each successful write must leave computed values ready so a subsequent get_cell is a constant-time cached read.

Implement eager_sheet(operations: string[][]) -> string[]. Each row is ["set", cell, raw] or ["get", cell]. Return one string per operation:

  • A successful set returns "OK" .
  • A set that would introduce a circular reference returns "CYCLE" and leaves the previous sheet unchanged.
  • A get returns the cell's computed integer in canonical decimal notation, with no leading plus or leading zeros; zero is "0" .

Formula and edit contract

The source describes formulas and dependency/cycle handling but does not give a grammar. This practice version explicitly uses:

  • Cell names are uppercase letters followed by a positive decimal row number with no leading zeros, such as A1 or AA10 .
  • Raw values are signed integer strings or formulas beginning with = .
  • Formula grammar is term (('+' | '-') term)* , where a term is a nonnegative integer or a cell reference. Spaces may surround tokens. Unary signs and parentheses inside formulas are excluded.
  • Unset cells evaluate to zero. Repeated references contribute repeatedly, so =A1+A1 counts the value twice.
  • Set replaces the entire previous definition, including its dependency links. It may change a literal to a formula or a formula to a literal.
  • Direct and indirect cycles are rejected before the edit becomes visible. A failed set preserves both the old definition and every previously computed value.
  • On a successful set, update every affected dependent value before processing the next operation. Implement get using stored results, without dependency traversal on reads.

Constraints

  • There are at most 500 operations and at most 100 terms per formula.
  • All names and expressions are syntactically valid.
  • Numeric tokens, stored literals, and all intermediate arithmetic results for an acyclic prospective sheet fit in a signed 32-bit integer.
  • The sheet starts empty, and operations are processed sequentially.
  • Cycle-error serialization, unset-cell behavior, grammar, and bounds are explicit practice assumptions. The constant-time-read requirement and the need to consider write-versus-read evaluation come from the reported task.

Examples

operations = [
  ["set","A1","2"],
  ["set","B1","=A1+1"],
  ["set","C1","=A1+B1"],
  ["set","A1","5"],
  ["get","C1"]
]
result = ["OK","OK","OK","OK","11"]
operations = [
  ["set","A1","=B1"],
  ["set","B1","=A1+1"],
  ["get","A1"],
  ["set","A1","3"],
  ["set","B1","=A1+1"],
  ["get","B1"]
]
result = ["OK","CYCLE","0","OK","OK","4"]

The rejected edit in the second example leaves B1 unset. Replacing A1 with a literal later removes the dependency that would have completed the cycle.

Submit Your Answer to Earn 20XP

Sign in to leave a comment

Loading comments...