Quick Overview

This question evaluates object-oriented design and stateful system skills, including time-ordered event processing, scheduling and cancellation semantics, balance accounting, and top-k aggregation using appropriate data structures.

Design a bank system with scheduled transfers

Company: Meta

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Take-home Project

## Bank System (OOD): Accounts, Transfers, Scheduling, Top Spending, Merge Design an in-memory banking system that supports: - account creation - deposits/withdrawals - immediate transfers - scheduled (delayed) transfers with cancellation - querying top spenders - merging accounts ### Core rules - Each account has a balance (integer, starts at 0). - Each operation is called with a `timestamp`. - Before executing any operation at time `t`, the system must **process all scheduled transfers** whose execution time `<= t`. - “Spending” for a customer is the total money sent out (withdrawals + transfers out, including scheduled transfers once executed; depending on your interpretation, you may also count scheduled transfers as spending when reserved—state your choice and be consistent). ### API 1. `create_account(timestamp, customer_id) -> bool` - Create if not exists. 2. `deposit(timestamp, customer_id, amount) -> bool` - Fail if account doesn’t exist. 3. `withdraw(timestamp, customer_id, amount) -> bool` - Fail if account doesn’t exist or insufficient funds. - Counts toward spending. 4. `transfer(timestamp, from_id, to_id, amount) -> bool` - Immediate transfer. - Fail if either account missing or insufficient funds. - Counts `amount` toward `from_id` spending. 5. `top_spending(timestamp, n) -> list<string>` - Return top `n` customers formatted `"customerId(total)"`. - Sort by total spending desc, then customerId asc. 6. `schedule_transfer(timestamp, from_id, to_id, amount, delay) -> string | null` - Create a transfer that will execute at `timestamp + delay`. - If invalid (missing accounts or insufficient funds), return `null`. - Return a unique `transfer_id` for cancellation. - Funds may be “reserved” immediately or deducted at execution; choose one and document it. 7. `cancel_transfer(timestamp, customer_id, transfer_id) -> bool` - Cancel only if: - `transfer_id` exists - status is still pending (not executed) - the `customer_id` is the sender - Return whether cancellation succeeded. 8. `merge_account(timestamp, from_id, to_id) -> bool` - Merge `from_id` into `to_id`: - Move remaining balance into `to_id` - Add spending totals - Update any **pending** scheduled transfers that reference `from_id` as sender or receiver to reference `to_id` - Delete `from_id` ### Notes - Assume up to ~1e5 operations. - You may use a min-heap/priority queue for scheduled transfers.

Quick Answer: This question evaluates object-oriented design and stateful system skills, including time-ordered event processing, scheduling and cancellation semantics, balance accounting, and top-k aggregation using appropriate data structures.

Implement an in-memory banking simulator. Write `solution(operations)` that processes the operations in order and returns a list of results, one per operation. Each operation is a tuple or list whose first element is the operation name: - `('create_account', timestamp, customer_id)` -> `bool` - `('deposit', timestamp, customer_id, amount)` -> `bool` - `('withdraw', timestamp, customer_id, amount)` -> `bool` - `('transfer', timestamp, from_id, to_id, amount)` -> `bool` - `('top_spending', timestamp, n)` -> `list[str]` - `('schedule_transfer', timestamp, from_id, to_id, amount, delay)` -> `str | None` - `('cancel_transfer', timestamp, customer_id, transfer_id)` -> `bool` - `('merge_account', timestamp, from_id, to_id)` -> `bool` Rules: - Every account starts with balance `0`. - Before executing any operation at time `t`, first execute all pending scheduled transfers with execution time `<= t`. - This problem uses **reservation semantics** for scheduled transfers: when a scheduled transfer is created successfully, its amount is removed from the sender immediately. - If a pending scheduled transfer is canceled, that reserved amount is refunded to the sender's current live account. - A scheduled transfer increases spending only when it actually executes. - If merges cause a pending scheduled transfer's sender and receiver to become the same live account, execution simply returns the reserved money to that account and does **not** increase spending. - `top_spending` considers only current live accounts and returns at most `n` strings formatted as `"customerId(total)"`, sorted by total spending descending, then `customer_id` ascending. - Successful scheduled transfers must return deterministic IDs: `'transfer1'`, `'transfer2'`, ... in order of successful scheduling. - A merged-away ID is deleted and cannot be created again. Return the result of every operation in order.

Constraints

  • `1 <= len(operations) <= 10^5`
  • Timestamps are integers in non-decreasing order.
  • `customer_id`, `from_id`, and `to_id` are non-empty strings and IDs are never reused after creation.
  • Amounts are positive integers; `delay` and `n` are non-negative integers.

Examples

Input: [('create_account', 1, 'alice'), ('create_account', 1, 'bob'), ('deposit', 2, 'alice', 100), ('transfer', 3, 'alice', 'bob', 30), ('withdraw', 4, 'bob', 10), ('top_spending', 5, 2)]

Expected Output: [True, True, True, True, True, ['alice(30)', 'bob(10)']]

Explanation: Alice sends 30 to Bob, and Bob withdraws 10. Spending totals are Alice=30 and Bob=10.

Input: [('create_account', 1, 'ann'), ('create_account', 1, 'ben'), ('deposit', 2, 'ann', 50), ('schedule_transfer', 3, 'ann', 'ben', 20, 5), ('top_spending', 4, 2), ('cancel_transfer', 7, 'ann', 'transfer1'), ('top_spending', 9, 2)]

Expected Output: [True, True, True, 'transfer1', ['ann(0)', 'ben(0)'], True, ['ann(0)', 'ben(0)']]

Explanation: The scheduled transfer reserves 20 immediately, but spending stays 0 until execution. It is canceled before time 8, so the money is refunded and no spending is added.

Hints

  1. A min-heap keyed by execution time is a natural way to process all scheduled transfers due before the current operation.
  2. Do not scan every pending transfer during `merge_account`. Instead, keep a mapping from old IDs to current live IDs and resolve them lazily when a scheduled transfer executes or is canceled.

Loading coding console...