An integer array is taken one element at a time, playing Subarray Sum Equals K (LC 560): how many contiguous subarrays sum to exactly k. Under the tiles runs the prefix line — P[j] drawn on the boundary between tiles, so P[i+1] − P[j] being the sum of tiles j..i is a picture rather than an identity. Under that sits the map: one bar per prefix value seen, stacked once per sighting. Each step extends the balance, draws a dashed line at P − k, lights every earlier prefix sitting on that line, and draws a green bracket under each subarray those prefixes name — that is the count going up. Only then is the current prefix recorded, which is why a k = 0 step never matches itself.
The piece has two other bookkeepings on the same array. Unseeded leaves the empty prefix {0: 1} out of the map: every step runs identically until a prefix lands exactly on k, and the subarray starting at index 0 goes by as a dashed red bracket with the reason written beside it. Sliding window runs the reflex answer — take on the right, shrink from the left while the sum is over k, count on equality — and it is correct on an all-positive array and wrong on almost any other: with a negative inside, taking an element can lower the sum and dropping one can raise it, so “sum > k, shrink” walks straight past matches. The missed brackets pile up in red under the running count while the true answer sits beside it. Hit positives only and the same window agrees with the map at every step, which is the precise property the interviewer is asking you to name.
Type your own array and k, step through, or let it run.
Reuse
src/ledger.js is a framework-free ES module:
makeArray(n, { lo, hi, rand })— a random small-integer array biased toward repeats, so prefix values collide.cleanArray(text, max)— integers out of free text, clamped, for user input.subarraySum(nums, k)— the plain answer, as you would write it in an interview.prefixes(nums)— P[0..n].simulate(nums, k, { mode })— one frame per element with the prefix, the value looked up, the subarray starts it found, the map snapshot, the ground-truth matches ending at that index, and which of them this bookkeeping missed.modeis'map','unseeded', or'window'(which reports the window’s edges and sum instead of a map). Same trace-per-tick shape asrho,sift,windowandastar-grid.
No rendering or timers in the module; the canvas demo is reference code.
Gotchas
- The map bars keep a fixed x-slot per prefix value across the whole run, so a bar grows in place instead of the row reshuffling under you.
- In window mode, k ≤ 0 on a positive array means the window is always empty after shrinking — nothing to count, correctly.
- The demo bundles its own copy of
ledger.js(self-contained by contract); re-copy after editingsrc/.