Build a Progressive Banking Ledger
Company: Anthropic
Role: Software Engineer
Category: Coding & Algorithms
Difficulty: hard
Interview Round: Onsite
# Build a Progressive Banking Ledger
The source reports the four feature stages but not exact ledger semantics. The APIs, event priorities, cashback timing, and merge rules below are deterministic practice assumptions.
Implement:
```python
def run_banking_ledger(
operations: list[list[object]],
cashback_delay: int,
) -> list[object]:
...
```
`cashback_delay` is a positive integer. Process operations in list order and return one result per operation.
## Stage 1: Accounts
- `["CREATE", timestamp, account_id] -> bool`: create an account with balance zero. Duplicate or retired IDs return `False`.
- `["DEPOSIT", timestamp, account_id, amount] -> int | None`: return the new balance, or `None` if the account is not active.
- `["TRANSFER", timestamp, source_id, target_id, amount] -> int | None`: atomically move funds and return the source's new balance. Return `None` for a missing account, equal IDs, or insufficient funds.
A successful transfer increases outgoing spend only for the source. Deposits do not count as outgoing spend.
## Stage 2: Spending Rank
- `["TOP_SPENDERS", timestamp, n] -> list[list[object]]` returns `[[account_id, outgoing_total], ...]` for up to `n` active accounts, sorted by outgoing total descending and account ID ascending. If `n <= 0`, return `[]`.
## Stage 3: Scheduled Payments and Cashback
- `["SCHEDULE", timestamp, account_id, amount, execute_at, cashback] -> str | None` creates `payment1`, `payment2`, and so on for successful schedules. It does not reserve funds. The account must be active, `execute_at` must be strictly later than `timestamp`, and `cashback` is a nonnegative integer.
- `["STATUS", timestamp, payment_id] -> str | None` returns `"scheduled"`, `"completed"`, or `"failed"`, or `None` for an unknown ID.
At execution time, a scheduled payment succeeds only if its current account has enough funds. Success subtracts `amount`, adds `amount` to that account's outgoing total, marks the payment completed, and schedules a credit of exactly `cashback` at `execute_at + cashback_delay`. Insufficient funds marks it failed and creates no cashback. A completed payment remains `"completed"` before and after its cashback is credited.
Before each well-formed API operation at timestamp `t`, process every event due at or before `t`. Order events by due timestamp, then process all payment executions by numeric payment ID, then all cashback credits by originating numeric payment ID. Thus a cashback due at a timestamp cannot fund a payment due at that same timestamp. Process the external operation only after that due-event batch.
## Stage 4: Merge and Historical Balance
- `["MERGE", timestamp, target_id, source_id] -> bool` merges two distinct active accounts. The target survives; the source becomes a historical alias and can never be recreated or used for new operations.
- `["BALANCE_AT", timestamp, account_id, as_of_timestamp] -> int | None` returns the historical balance after all already-processed events and operations at or before `as_of_timestamp`, or `None` if that ID did not yet exist.
A merge first processes due events, then combines current balances and outgoing totals. Pending payments and cashbacks owned by the source are rebound to the target. Their IDs and statuses do not change. At and after the merge timestamp, historical queries using either merged ID return the surviving lineage's combined balance. Before the merge timestamp, each ID returns its independent balance. Apply the same rule through chained merges: an alias follows a later surviving account only from each merge timestamp onward.
Record merge snapshots as ledger events. A cashback created before a merge but credited afterward goes to the then-current survivor. A scheduled payment rebound by a merge spends from the survivor and adds to its combined outgoing total.
## Ordering, Failures, and Validation
- Timestamps are nonnegative and nondecreasing. Operations sharing a timestamp execute in list order after the due-event rule above.
- Amounts are positive integers; cashback is nonnegative; `as_of_timestamp` is nonnegative and cannot exceed the query timestamp.
- Ordinary domain failures use `False` or `None` exactly as specified and are atomic after mandatory due events have run.
- Validate command shape, types, timestamp order, amount ranges, and historical-query bounds before processing events. Invalid input or an unknown command raises `ValueError` without any state change.
Analyze event-queue, ranking, merge-alias, and historical-query complexity. Test same-time payments and cashback, failure at execution, cashback after a chained merge, pre- and post-merge history, and retired-ID reuse.
Quick Answer: Implement a timestamped banking ledger with deposits, transfers, spender rankings, scheduled payments, cashback, account merges, and historical balances. The challenge centers on deterministic event ordering, immutable payment status, alias lineage, and atomic failure handling.
Process account, transfer, spending-rank, scheduled-payment, cashback, merge, and historical-balance operations with deterministic due-event ordering and one result per operation.
Constraints
- Timestamps are nonnegative and nondecreasing
- Payment executions at a due time precede cashback credits
- Merged IDs are retired aliases and cannot be recreated
Examples
Input: {'operations': [], 'cashback_delay': 5}
Expected Output: []
Explanation: An empty operation stream has no results.
Input: {'operations': [['CREATE', 0, 'a'], ['CREATE', 0, 'b'], ['DEPOSIT', 1, 'a', 100], ['TRANSFER', 2, 'a', 'b', 30], ['TOP_SPENDERS', 3, 2]], 'cashback_delay': 5}
Expected Output: [True, True, 100, 70, [['a', 30], ['b', 0]]]
Explanation: Transfers move funds and count as outgoing only for the source.
Hints
- Represent payment executions and cashback credits in one priority queue ordered by time, kind, and numeric payment ID.
- Persist balance snapshots together with alias links so historical queries can resolve the lineage that existed at the requested time.