Home/Data structures & algorithms/Stacks and nested operations

Stacks and nested operations

Validate last-in-first-out order with a stack

A trace records resources loaded inside nested scopes and unloaded as those scopes exit. Counts alone can look correct even when the nesting is wrong: LOAD:a, LOAD:b, UNLOAD:a, UNLOAD:b loads and unloads both labels, but closes the outer resource while the inner one is still active.

A stack keeps exactly the information the trace needs: which unfinished operation must close next. Sorting the tokens or counting each label would discard that order.

Checking the order of nested resources

A stack represents operations that have opened but have not yet closed. Last-in-first-out ordering means the next close must match the most recently opened label. Merely checking whether the label occurs anywhere among open operations accepts invalid nesting.

For LOAD:a, LOAD:b, UNLOAD:a, the a exists but b is still on top. The sequence must fail at that unload. A simple prototype can cancel adjacent matching pairs; the final stack records the same nesting state directly.

Closing the most recent load

Process one token at a time and distinguish malformed input from valid syntax with invalid order. Each reached token requires one colon, an exact command name, and a nonempty label. Then a load pushes its label; an unload must match the top before removing it. End-of-input succeeds only when no unmatched loads remain.

Failure order is part of the API. After an unload ordering violation, return false immediately, without validating a later token. Thus ["UNLOAD:x", "bad"] returns false, while a reached "LOAD:" throws. A prototype that globally parses all tokens first would change this observable contract.

JavaScript arrays support push/pop at the end without shifting an entire prefix. Return actual boolean true/false, rather than a remaining length or an object that happens to be truthy.

JavaScript
const pending = ["a", "b"];
console.log(pending.at(-1)); // b: only this label may close next
pending.pop();
console.log(pending); // ["a"]

Stopping at the first invalid operation

The stack costs O(n) token operations plus parsing time proportional to token text, and O(d) pending labels for maximum nesting depth d. Adjacent reduction can revisit many positions and be quadratic. This mechanism applies to nested scopes and undo lifecycles when closures must match openings; it does not model operations that can finish out of order.

Balanced load/unload totals are only part of the trace contract; the resource lifetimes must also nest correctly.

Practice Stacks and nested operations

Implement the exercise in a full-screen workspace, then run its tests.

Open practice
Next lessonMonotonic deques