Banking System (Online Assessment)
Problem
Overview
Your task is to implement an in-memory banking system. This problem consists of 4 levels that progressively add complexity:
- Level 1: Basic account operations (create, deposit, transfer)
- Level 2: Ranking accounts by spending activity
- Level 3: Scheduled payments with cashback and payment status tracking
- Level 4: Account merging and historical balance queries
Subsequent levels are unlocked when the current level is correctly solved. You always have access to the data for the current and all previous levels.
Level 1: Basic Account Operations
Description
Initially, the banking system does not contain any accounts. Implement operations to allow account creation, deposits, and transfers between different accounts.
Operations
create_account
create_account(self, timestamp: int, account_id: str) -> bool
- Creates a new account with the given identifier if it doesn't already exist
- Returns
Trueif the account was successfully created - Returns
Falseif an account with that id already exists
deposit
deposit(self, timestamp: int, account_id: str, amount: int) -> int | None
- Deposits the given amount of money to the specified account id
- Returns the balance of the account after the operation has been processed
- Returns
Noneif the specified account doesn't exist - The operation is processed before the result is returned
transfer
transfer(self, timestamp: int, source_account_id: str, target_account_id: str, amount: int) -> int | None
- Transfers the given amount of money from
source_account_idtotarget_account_id - Returns the balance of
source_account_idif the transfer was successful - Returns
Noneotherwise
Returns None if:
source_account_idortarget_account_iddoesn't existsource_account_idandtarget_account_idare the same- Account
source_account_idhas insufficient funds to perform the transfer
Level 2: Top Spenders
Description
The bank wants to identify people who are not keeping money in their accounts. Implement operations to support ranking accounts based on outgoing transactions.
New Operations
top_spenders
top_spenders(self, timestamp: int, n: int) -> list[str]
- Returns the identifiers of the top
naccounts with the highest outgoing transactions - Outgoing transactions = total amount of money either:
- Transferred out, OR
- Paid/withdrawn (the
payoperation will be introduced in Level 3)
- Results are sorted in descending order by total outgoing amount
- In case of a tie, sort alphabetically by
account_idin ascending order
Format:
["account_id_1(total_outgoing_1)", "account_id_2(total_outgoing_2)", ..., "account_id_n(total_outgoing_n)"]
Notes:
- If less than
naccounts exist in the system, return all their identifiers in the described format - Cashback (an operation introduced in Level 3) should not be reflected in calculations for total outgoing transactions
Level 3: Scheduled Payments with Cashback
Description
The banking system should allow scheduling payments with cashback and checking the status of scheduled payments.
New Operations
pay
pay(self, timestamp: int, account_id: str, amount: int) -> str | None
- Withdraws the given amount of money from the specified account
- All withdrawal transactions provide a 2% cashback
- The cashback amount (rounded down to the nearest integer) will be refunded to the account 24 hours after the withdrawal
- Returns a unique identifier for the payment transaction (e.g.,
"payment1","payment2", etc.)
Returns None if:
account_iddoesn't existaccount_idhas insufficient funds to perform the payment
Additional Conditions:
top_spendersshould now also account for the total amount of money withdrawn from accounts- The waiting period for cashback is 24 hours = 24 × 60 × 60 × 1000 = 86400000 milliseconds (the unit for timestamps)
- Cashback will be processed at
timestamp + 86400000 - If the refund is successful (i.e., the account hasn't been removed from the system), the cashback is applied
get_payment_status
get_payment_status(self, timestamp: int, account_id: str, payment: str) -> str | None
- Returns the status of the payment transaction for the given
payment
Returns None if:
account_iddoesn't exist- The given
paymentdoesn't exist for the specified account - The payment transaction was for an account with a different identifier from
account_id
Returns:
"IN_PROGRESS"- if cashback has not been received yet"CASHBACK_RECEIVED"- if cashback has been refunded to the account
Level 4: Account Merging and Historical Balances
Description
The banking system should support merging two accounts while retaining both accounts' balance and transaction histories.
New Operations
merge_accounts
merge_accounts(self, timestamp: int, account_id_1: str, account_id_2: str) -> bool
- Merges
account_id_2intoaccount_id_1 - Returns
Trueif accounts were successfully merged - Returns
Falseotherwise
Returns False if:
account_id_1is equal toaccount_id_2account_id_1oraccount_id_2doesn't exist
Merge Behavior:
- All pending cashback refunds for
account_id_2should still be processed, but refunded toaccount_id_1instead - After the merge, it must be possible to check the status of payment transactions in
account_id_2with payment identifiers by replacingaccount_id_2withaccount_id_1 - The balance of
account_id_2should be added to the balance foraccount_id_1 top_spendersoperations should recognize merged accounts — the total outgoing transactions for merged accounts should be the sum of all money transferred and/or withdrawn in both accountsaccount_id_2should be removed from the system after the merge
get_balance
get_balance(self, timestamp: int, account_id: str, time_at: int) -> int | None
- Returns the total amount of money in the account
account_idat the given timestamptime_at - If the specified account did not exist at a given time
time_at, returnsNone
Important Notes:
- If queries have been processed at timestamp
time_at,get_balancemust reflect the account balance after the query has been processed - If the account was merged into another account, the merged account should inherit its balance history
Important Edge Cases
Account Recreation After Merge
- If
account_id_2is merged intoaccount_id_1, thenaccount_id_2is removed from the system - After removal, it is possible to create a new account with
account_id_2usingcreate_account - Historical balances and outgoing transaction totals before the merge are preserved in
account_id_1 - The new
account_id_2account starts with a balance of 0 from the new creation timestamp
Historical Queries After Merge
- If an account was merged at timestamp T, queries with
time_at < Tshould return the account's historical balance - Queries with
time_at >= Tfor a merged account should returnNone(unless the account was recreated)
Constraints
- All timestamps are given in milliseconds
- Timestamps are guaranteed to be unique and in strictly increasing order
- Account IDs are valid string identifiers
- All amounts are positive integers
Solution
Sign in to get AI feedback on your answer. Your work is saved while you do.
Sign in to evaluate