Simulate a Bank Ledger With Validated Transfers, Deposits and Withdrawals

Read the full interview experience this question came from →

Quick Overview

A coding exercise that simulates a bank's in-memory ledger: apply an ordered sequence of transfers, deposits and withdrawals across numbered accounts and report which requests succeed. It tests careful validation of account numbers and balances, ordered state updates, and 64-bit arithmetic.

Simulate a Bank Ledger With Validated Transfers, Deposits and Withdrawals

Company: Capital One

Role: Software Engineer

Category: Coding & Algorithms

Difficulty: medium

Interview Round: Other

A retail bank's core system keeps every account's balance in memory and must apply a stream of customer requests strictly in the order they arrive. Each request is a transfer between two accounts, a deposit, or a withdrawal. A request is rejected, and leaves every balance untouched, when it names an account that does not exist or when it would take an account's balance below zero. Write a function that applies all requests in order and reports, for each one, whether it succeeded. ### Function Signature ```python def process_bank_operations(balance: List[int], ops: List[str], args: List[List[int]]) -> List[bool]: ``` ### Rules - There are `n = len(balance)` accounts, numbered `1` to `n`. Account `i` starts with balance `balance[i - 1]`. - `ops[j]` and `args[j]` describe request `j` (0-indexed). Requests are applied in index order, and each one sees the balances left by the requests before it. - `"transfer"` with `args[j] = [from_account, to_account, money]` succeeds only if both account numbers are between `1` and `n` and the balance of `from_account` is at least `money`. On success, `money` moves from `from_account` to `to_account`. A transfer with `from_account == to_account` goes through the same checks and, if it succeeds, leaves the balance unchanged. - `"deposit"` with `args[j] = [account, money]` succeeds only if `account` is between `1` and `n`; on success it adds `money` to that account. - `"withdraw"` with `args[j] = [account, money]` succeeds only if `account` is between `1` and `n` and its balance is at least `money`; on success it subtracts `money`. - A request that fails changes no balance. - Return a list of length `len(ops)` whose element `j` is `True` if request `j` succeeded and `False` otherwise. ### Constraints - `1 <= n <= 10^4` - `0 <= balance[i] <= 10^11` - `1 <= len(ops) == len(args) <= 10^4` - Every `ops[j]` is exactly one of `"transfer"`, `"deposit"`, `"withdraw"`; `args[j]` has length 3 for a transfer and length 2 for a deposit or a withdrawal. - Every account number in `args` satisfies `1 <= account <= 10^5`, so it may be larger than `n`. - Every amount satisfies `0 <= money <= 10^11`. - Balances and amounts exceed the 32-bit signed range (`2^31 - 1`), so use 64-bit integers. Under these bounds no balance ever exceeds `2 * 10^15`, well within `2^53`. ### Examples Example 1 ```text balance = [50, 0, 75] ops = ["deposit", "withdraw", "transfer", "transfer", "withdraw"] args = [[2, 40], [1, 60], [3, 2, 75], [2, 4, 10], [3, 1]] output = [True, False, True, False, False] ``` - Deposit 40 into account 2: balances become `[50, 40, 75]`. - Withdraw 60 from account 1: only 50 is available, so it fails. - Transfer 75 from account 3 to account 2: exactly enough, so balances become `[50, 115, 0]`. - Transfer from account 2 to account 4: account 4 does not exist, so it fails. - Withdraw 1 from account 3: its balance is 0, so it fails. Example 2 ```text balance = [5] ops = ["transfer", "withdraw", "deposit", "transfer"] args = [[1, 1, 5], [1, 0], [2, 3], [1, 1, 6]] output = [True, True, False, False] ``` - A self-transfer of 5 from an account holding 5 succeeds and changes nothing. - Withdrawing 0 succeeds. - Account 2 does not exist, so the deposit fails. - A self-transfer of 6 fails because the balance is only 5.

Overview: A coding exercise that simulates a bank's in-memory ledger: apply an ordered sequence of transfers, deposits and withdrawals across numbered accounts and report which requests succeed. It tests careful validation of account numbers and balances, ordered state updates, and 64-bit arithmetic.

Read the full Capital One Software Engineer interview experience this question came from

Capital One logo
Capital One
Apr 19, 2026
mediumSoftware EngineerOtherCoding & Algorithms
0
0

A retail bank's core system keeps every account's balance in memory and must apply a stream of customer requests strictly in the order they arrive. Each request is a transfer between two accounts, a deposit, or a withdrawal. A request is rejected, and leaves every balance untouched, when it names an account that does not exist or when it would take an account's balance below zero.

Write a function that applies all requests in order and reports, for each one, whether it succeeded.

Function Signature

def process_bank_operations(balance: List[int], ops: List[str], args: List[List[int]]) -> List[bool]:

Rules

  • There are n = len(balance) accounts, numbered 1 to n . Account i starts with balance balance[i - 1] .
  • ops[j] and args[j] describe request j (0-indexed). Requests are applied in index order, and each one sees the balances left by the requests before it.
  • "transfer" with args[j] = [from_account, to_account, money] succeeds only if both account numbers are between 1 and n and the balance of from_account is at least money . On success, money moves from from_account to to_account . A transfer with from_account == to_account goes through the same checks and, if it succeeds, leaves the balance unchanged.
  • "deposit" with args[j] = [account, money] succeeds only if account is between 1 and n ; on success it adds money to that account.
  • "withdraw" with args[j] = [account, money] succeeds only if account is between 1 and n and its balance is at least money ; on success it subtracts money .
  • A request that fails changes no balance.
  • Return a list of length len(ops) whose element j is True if request j succeeded and False otherwise.

Constraints

  • 1 <= n <= 10^4
  • 0 <= balance[i] <= 10^11
  • 1 <= len(ops) == len(args) <= 10^4
  • Every ops[j] is exactly one of "transfer" , "deposit" , "withdraw" ; args[j] has length 3 for a transfer and length 2 for a deposit or a withdrawal.
  • Every account number in args satisfies 1 <= account <= 10^5 , so it may be larger than n .
  • Every amount satisfies 0 <= money <= 10^11 .
  • Balances and amounts exceed the 32-bit signed range ( 2^31 - 1 ), so use 64-bit integers. Under these bounds no balance ever exceeds 2 * 10^15 , well within 2^53 .

Examples

Example 1

balance = [50, 0, 75]
ops     = ["deposit", "withdraw", "transfer", "transfer", "withdraw"]
args    = [[2, 40], [1, 60], [3, 2, 75], [2, 4, 10], [3, 1]]
output  = [True, False, True, False, False]
  • Deposit 40 into account 2: balances become [50, 40, 75] .
  • Withdraw 60 from account 1: only 50 is available, so it fails.
  • Transfer 75 from account 3 to account 2: exactly enough, so balances become [50, 115, 0] .
  • Transfer from account 2 to account 4: account 4 does not exist, so it fails.
  • Withdraw 1 from account 3: its balance is 0, so it fails.

Example 2

balance = [5]
ops     = ["transfer", "withdraw", "deposit", "transfer"]
args    = [[1, 1, 5], [1, 0], [2, 3], [1, 1, 6]]
output  = [True, True, False, False]
  • A self-transfer of 5 from an account holding 5 succeeds and changes nothing.
  • Withdrawing 0 succeeds.
  • Account 2 does not exist, so the deposit fails.
  • A self-transfer of 6 fails because the balance is only 5.