ID Allocator II
Manage the fixed ID space [0, 999] — 1000 IDs — divided into named buckets that occupy contiguous, non-overlapping ranges. Implement two operations.
pack(requests)
Given (name, size) pairs in order, pack the buckets contiguously from ID 0 upward, preserving order, and return the layout as [name, start, end] triples.
- A zero-size bucket appears as [name, -1, -1] and does not advance the cursor.
- A negative size is an error.
- If the sizes sum past 1000, fail without allocating anything.
pack([["a", 100], ["b", 200], ["c", 50]]) => [["a", 0, 99], ["b", 100, 299], ["c", 300, 349]]
resize(buckets, name, newSize)
Given a packed layout, resize one bucket to own exactly newSize IDs:
- Feasibility first: if total − currentSize + newSize > 1000, fail without mutating the layout.
- The target keeps its start. Growth extends its end and shifts every later bucket right by the delta; shrinking pulls its end in and later buckets close the gap.
- An unknown name or a negative size is an error.
resize([["a", 0, 99], ["b", 100, 299], ["c", 300, 349]], "a", 150) => [["a", 0, 149], ["b", 150, 349], ["c", 350, 399]] resize([["a", 0, 99], ["b", 100, 299], ["c", 300, 349]], "a", 50) => [["a", 0, 49], ["b", 50, 249], ["c", 250, 299]]
Hints
Hint 1
pack is one cursor sweep — but validate every size and the total before you place anything, so a late failure can't leave a half-built layout.
Hint 2
resize is a delta: newSize − currentSize. Buckets before the target are untouched; the target's end moves by the delta; every later bucket shifts start and end by the same delta.
Hint 3
All-or-nothing means check feasibility against the sum of sizes first and build the result as a new layout — never edit the input in place.