Banking Transfers, Account Merges, and Historical Balances
Problem statement
Implement a banking system that processes an ordered batch of operations. It supports basic accounts, settled transaction activity, pending transfers, account merging, and historical balances. Return one string per operation.
Time and result rules
- Each row begins with an operation name and an integer millisecond timestamp. Timestamps are strictly increasing.
- Return lowercase
trueorfalsefor boolean results, base-10 strings for numbers, and the empty string for an unavailable numeric or transfer-ID result. - A transfer created at time
scan be accepted throughs + 86400000. It expires ats + 86400001. Before any operation at timet, process every expiry at or beforet, recording its refund at the expiry time. - Rejected operations leave state unchanged, apart from expiries that must already have been processed.
Basic accounts and activity
["CREATE_ACCOUNT", t, id]: create an active account with balance and activity zero. Returntrue, orfalseif that ID is already active. A removed ID may be created again as a fresh account; older history remains queryable.["DEPOSIT", t, id, amount]: credit a positive amount and return the balance, or the empty string for a missing account.["PAY", t, id, amount]: debit a positive amount and return the balance, or the empty string for a missing account or insufficient funds.["TOP_ACTIVITY", t, n]: return up tonactive accounts ordered by settled transaction total descending, then ID lexicographically ascending. Format each entry asid(total), joined with,. Return the empty string if there are no active accounts.- Settled activity counts deposits, successful payments, and the amount on both sides of an accepted transfer. A hold, refund, expiry, or merge adds no new transaction activity.
Pending transfers
["TRANSFER", t, source, target, amount]: immediately subtract and hold the positive amount from the source. Return the next global IDtransfer1,transfer2, and so on. Reject with the empty string if either account is missing, the IDs are equal, or the source has insufficient funds. Only successful initiations consume an ID.["ACCEPT_TRANSFER", t, id, transferId]: returntrueonly if the transfer is pending andidis its current target. Credit that target, settle the hold, and add the amount to both accounts' activity totals. Otherwise returnfalse.- Pending money is unsettled; it contributes to neither account's settled activity until acceptance. An expiry or cancellation refunds the hold to its source without changing activity.
Account merges
["MERGE_ACCOUNTS", t, first, second] merges the second account into the first. Return false if either account is missing or the IDs are equal. Otherwise perform these steps and return true:
- Cancel and refund every pending transfer whose source is the second account.
- Cancel and refund every pending transfer from the first account to the second account.
- Redirect every other pending transfer targeting the second account to the first account. Other pending transfers remain unchanged.
- Add the second account's resulting balance and settled activity total to the first account, then remove the second account.
Historical balances
["GET_BALANCE", t, id, timeAt] returns that ID's balance after all activity at timeAt, or after the latest earlier activity if no event occurred exactly then. Return the empty string if the ID did not exist at that time.
- Before a merge, each account retains its separate history. At the merge timestamp, the surviving account has the combined balance and the removed account stops existing.
- A removed account remains queryable for times when it existed. A later recreation does not rewrite that history; it starts a new existence interval with zero balance and activity.
- When expiry and an external operation share a timestamp, historical balance at that timestamp includes both, with expiry processed first.
Function
processBankingOperations(operations: String[][]) → String[]Examples
Example 1
operations = [["CREATE_ACCOUNT","1","a"],["CREATE_ACCOUNT","2","b"],["DEPOSIT","3","a","100"],["TRANSFER","4","a","b","30"],["TOP_ACTIVITY","5","2"],["ACCEPT_TRANSFER","6","b","transfer1"],["TOP_ACTIVITY","7","2"],["GET_BALANCE","8","a","4"]]return = ["true","true","100","transfer1","a(100), b(0)","true","a(130), b(30)","70"]The transfer immediately holds 30 from a, leaving 70, but adds no settled activity yet. Acceptance credits b and adds 30 to each activity total. The historical query returns a's balance after the hold.
Example 2
operations = [["CREATE_ACCOUNT","1","a"],["CREATE_ACCOUNT","2","b"],["CREATE_ACCOUNT","3","c"],["DEPOSIT","4","a","100"],["DEPOSIT","5","b","50"],["DEPOSIT","6","c","80"],["TRANSFER","7","b","c","20"],["TRANSFER","8","a","b","10"],["TRANSFER","9","c","b","30"],["MERGE_ACCOUNTS","10","a","b"],["ACCEPT_TRANSFER","11","a","transfer3"],["TOP_ACTIVITY","12","3"],["GET_BALANCE","13","b","7"],["GET_BALANCE","14","b","10"]]return = ["true","true","true","100","50","80","transfer1","transfer2","transfer3","true","true","a(180), c(110)","30",""]Merging b into a cancels b's outgoing transfer and a's transfer to b, refunding both holds before combining balances into 150. The pending c-to-b transfer now targets a; acceptance raises a to 180. The removed b still had balance 30 at time 7, but did not exist after the merge at time 10.
Example 3
operations = [["CREATE_ACCOUNT","1","a"],["CREATE_ACCOUNT","2","b"],["DEPOSIT","3","a","100"],["TRANSFER","10","a","b","40"],["GET_BALANCE","86400010","a","86400010"],["ACCEPT_TRANSFER","86400011","b","transfer1"],["GET_BALANCE","86400012","a","86400011"],["TOP_ACTIVITY","86400013","2"]]return = ["true","true","100","transfer1","60","false","100","a(100), b(0)"]The transfer remains pending through time 86400010. At 86400011 its 40 is refunded before acceptance is attempted, so acceptance fails. The refund belongs to the expiry timestamp and changes no activity total.
Constraints
1 <= operations.length <= 1000.- Each external timestamp is a distinct integer in
[1, 10^9], in increasing order. For historical queries,0 <= timeAt <= t. - Every row is well formed. Amounts are integers in
[1, 10^9];1 <= n <= 1000. - Account IDs are 1 to 20 lowercase ASCII letters or digits. Transfer IDs in acceptance requests are nonempty strings of at most 30 ASCII letters or digits.
- Use signed 64-bit integers for balances and activity totals.