Code Editor with Block Shrink and Expand (Code Folding)
Company: Jane Street
Role: Machine Learning Engineer
Category: Coding & Algorithms
Difficulty: medium
Interview Round: Technical Screen
Quick Answer: This question evaluates a candidate's ability to model and manipulate indentation-based hierarchical structures, maintain nested visibility state for collapsed blocks, and map between original file lines and dynamic display numbering.
Constraints
- 1 <= number of lines <= 10^4; each line has at most 200 characters.
- Indentation is spaces only, always a multiple of 4; the first line has indentation 0.
- A line's indentation is at most one level (4 spaces) deeper than the previous line.
- Up to 10^4 total shrink / expand / render operations.
- Every shrink/expand receives a display number d that is valid for the current render state (1 <= d <= number of visible lines).
Examples
Input: (['a = 1', 'for i in range(10):', ' print(i)', ' print(i ** 2)', 'b = 10'], [['render'], ['shrink', 2], ['render'], ['expand', 2], ['render']])
Expected Output: [['1 a = 1', '2 + for i in range(10):', '3 print(i)', '4 print(i ** 2)', '5 b = 10'], ['1 a = 1', '2 + for i in range(10):', '3 b = 10'], ['1 a = 1', '2 + for i in range(10):', '3 print(i)', '4 print(i ** 2)', '5 b = 10']]
Explanation: Canonical example: render, shrink the for-loop, render (body hidden + renumbered), expand, render (restored).
Input: (['def f():', ' for i in x:', ' a = 1', ' b = 2', ' c = 3', 'd = 4'], [['render'], ['shrink', 2], ['render'], ['shrink', 1], ['render'], ['expand', 1], ['render']])
Expected Output: [['1 + def f():', '2 + for i in x:', '3 a = 1', '4 b = 2', '5 c = 3', '6 d = 4'], ['1 + def f():', '2 + for i in x:', '3 c = 3', '4 d = 4'], ['1 + def f():', '2 d = 4'], ['1 + def f():', '2 + for i in x:', '3 c = 3', '4 d = 4']]
Explanation: Nested blocks: collapse inner for-loop, collapse outer def, expand outer while inner stays collapsed.
Input: (['x = 1'], [['render']])
Expected Output: [['1 x = 1']]
Explanation: Edge: single line file, no block headers.
Input: (['a = 1', 'if x:', ' y = 2', 'z = 3'], [['render'], ['shrink', 1], ['render'], ['shrink', 2], ['shrink', 2], ['render']])
Expected Output: [['1 a = 1', '2 + if x:', '3 y = 2', '4 z = 3'], ['1 a = 1', '2 + if x:', '3 y = 2', '4 z = 3'], ['1 a = 1', '2 + if x:', '3 z = 3']]
Explanation: No-op cases: shrink a non-header (line 1) and shrink an already-collapsed header twice.
Input: (['outer:', ' mid:', ' deep', ' tail'], [['shrink', 2], ['shrink', 1], ['expand', 1], ['render']])
Expected Output: [['1 + outer:', '2 + mid:', '3 tail']]
Explanation: Expand outer while nested 'mid' header remains collapsed: 'deep' stays hidden, 'tail' reappears.
Hints
- Precompute each line's indentation (leading spaces) and whether it is a block header: line i is a header iff line i+1 has strictly greater indentation.
- Store a boolean collapsed flag per line. A line is visible iff none of the headers whose blocks contain it are collapsed.
- To map a display number to a real line and to render, scan top-to-bottom: when you reach a visible collapsed header, jump past every following line whose indentation is greater than the header's (its entire block, including any nested headers).
- shrink/expand only toggle the targeted header's own flag. Nested headers keep independent state, which is why expanding an outer block leaves inner collapsed blocks folded.