Account balances from a transaction log
A payments system receives a log of transactions and must turn it into account statements. Each log entry is a string with four comma-separated fields:
transaction_id,account_id,amount,timestamp
-
transaction_id: a unique, non-empty string. -
account_id: a non-empty string that names a customer or business account. -
amount: an integer. A positive amount is a deposit and a negative amount is a withdrawal. Use minor units such as cents. -
timestamp: an integer. Entries may arrive out of timestamp order.
Every account starts at 0. Apply transactions in timestamp order. When two transactions have the same timestamp, apply them in the order they appear in the log. Skip malformed lines, meaning a wrong field count, an empty id, or a non-integer number. Apply a repeated transaction_id only once.
Implement AccountBalanceProcessor:
-
balances(logs) -> List[Tuple[str, int]]: returns each account with a nonzero final balance, sorted by account id. Balances may go negative. -
balances_rejecting_overdrafts(logs): rejects any transaction that would make its account's balance negative. A rejected transaction leaves the balance unchanged. Returns the final statement and the ids of rejected transactions, in the order they were applied. -
AccountBalanceProcessor(platform)andbalances_with_coverage(logs): no transaction is rejected. When a non-platform account would go negative, the platform account pays the shortfall, so the account ends at exactly 0 and the platform is debited by the same amount. The platform's own transactions are never covered. Returns the final statement and the total amount the platform covered.
Constraints
- Up to 10^5 log lines; amounts fit in 64-bit integers.
Example
logs = ["t1,alice,100,1", "t2,bob,50,2", "t3,alice,-30,3",
"t4,bob,-80,4", "t5,carol,20,5"]
Part 1: [("alice", 70), ("bob", -30), ("carol", 20)]
Part 2: [("alice", 70), ("bob", 50), ("carol", 20)], rejected ["t4"]
Part 3 (platform = "platform"):
[("alice", 70), ("carol", 20), ("platform", -30)], covered 30
Out of order
logs = ["x2,dan,-40,20", "x1,dan,50,10"]
Part 1: [("dan", 10)] Part 2: nothing rejected, because x1 applies first
Interviewers usually add the parts one at a time. Later follow-ups can include multiple currencies, repaying the platform's coverage from later deposits, and settling all balances to zero with the fewest transfers.
Sign in to see the worked answer
The full answer, chapter by chapter, with what interviewers expect at each level. Free with an account: one full answer per company.
