Simple Bank System
Problem
A bank has n accounts numbered 1 to n. A 0-indexed array balance gives the starting balance of each account, where account i + 1 holds balance[i] dollars. Build a Bank class that processes a stream of transactions and reports whether each one succeeds.
A transaction is valid only if every account number it touches is in range 1 ≤ account ≤ n, and the source account holds at least the amount being withdrawn or transferred.
transfer(a1, a2, money)— movemoneyfrom accounta1toa2.deposit(a, money)— addmoneyto accounta(only the account must exist).withdraw(a, money)— removemoneyfrom accountaif it has enough.
Each method returns true if the transaction was applied, false otherwise.
balance = [10, 100, 20, 50, 30]; withdraw(3,10), transfer(5,1,20), deposit(5,20), transfer(3,4,15), withdraw(10,50)[true, true, true, false, false]class Bank:
def __init__(self, balance):
self.bal = balance # 0-indexed; account a -> bal[a-1]
self.n = len(balance)
def _valid(self, a):
return 1 <= a <= self.n # account number in range?
def transfer(self, a1, a2, money):
if not self._valid(a1) or not self._valid(a2):
return False
if self.bal[a1 - 1] < money: # enough funds at source?
return False
self.bal[a1 - 1] -= money
self.bal[a2 - 1] += money
return True
def deposit(self, a, money):
if not self._valid(a):
return False
self.bal[a - 1] += money
return True
def withdraw(self, a, money):
if not self._valid(a) or self.bal[a - 1] < money:
return False
self.bal[a - 1] -= money
return True
class Bank {
constructor(balance) {
this.bal = balance; // 0-indexed; account a -> bal[a-1]
this.n = balance.length;
}
valid(a) {
return a >= 1 && a <= this.n; // account number in range?
}
transfer(a1, a2, money) {
if (!this.valid(a1) || !this.valid(a2)) return false;
if (this.bal[a1 - 1] < money) return false; // enough funds?
this.bal[a1 - 1] -= money;
this.bal[a2 - 1] += money;
return true;
}
deposit(a, money) {
if (!this.valid(a)) return false;
this.bal[a - 1] += money;
return true;
}
withdraw(a, money) {
if (!this.valid(a) || this.bal[a - 1] < money) return false;
this.bal[a - 1] -= money;
return true;
}
}
class Bank {
long[] bal; // 0-indexed; account a -> bal[a-1]
int n;
public Bank(long[] balance) {
bal = balance;
n = balance.length;
}
private boolean valid(int a) {
return a >= 1 && a <= n; // account number in range?
}
public boolean transfer(int a1, int a2, long money) {
if (!valid(a1) || !valid(a2)) return false;
if (bal[a1 - 1] < money) return false; // enough funds?
bal[a1 - 1] -= money;
bal[a2 - 1] += money;
return true;
}
public boolean deposit(int a, long money) {
if (!valid(a)) return false;
bal[a - 1] += money;
return true;
}
public boolean withdraw(int a, long money) {
if (!valid(a) || bal[a - 1] < money) return false;
bal[a - 1] -= money;
return true;
}
}
class Bank {
vector<long long> bal; // 0-indexed; account a -> bal[a-1]
int n;
bool valid(int a) {
return a >= 1 && a <= n; // account number in range?
}
public:
Bank(vector<long long>& balance) : bal(balance), n(balance.size()) {}
bool transfer(int a1, int a2, long long money) {
if (!valid(a1) || !valid(a2)) return false;
if (bal[a1 - 1] < money) return false; // enough funds?
bal[a1 - 1] -= money;
bal[a2 - 1] += money;
return true;
}
bool deposit(int a, long long money) {
if (!valid(a)) return false;
bal[a - 1] += money;
return true;
}
bool withdraw(int a, long long money) {
if (!valid(a) || bal[a - 1] < money) return false;
bal[a - 1] -= money;
return true;
}
};
Explanation
This is a direct simulation problem. There is no clever data structure to discover — the whole job is to store the balances and faithfully apply each transaction only when it is valid.
The balances live in a plain array. Because accounts are numbered from 1 but the array is 0-indexed, account a maps to index a - 1. Getting this off-by-one right is the most common source of bugs here.
Every operation runs the same two guard checks before touching any money. First, existence: each account number must satisfy 1 ≤ a ≤ n. Second, solvency: for a withdraw or the source of a transfer, the balance must be at least money. A deposit only needs the existence check, since adding money can never overdraw.
If either guard fails, we return false and leave all balances untouched — the transaction is rejected as a whole, never partially applied. If both guards pass, we adjust the balance(s) and return true.
In the worked example, withdraw(10, 50) fails the existence check because there are only 5 accounts, and transfer(3, 4, 15) fails the solvency check because account 3 was already drawn down to $10. Because money values can reach 1012, languages like Java and C++ use 64-bit integers (long / long long) to avoid overflow.