Custom Exception: Insufficient Funds
Problem
An account starts with balance 0. Commands: deposit x (print balance B) and withdraw x. A withdrawal that is bigger than the balance must throw your own exception that carries the missing amount. The caller catches it and prints error: short by K, where K is how much is missing; the balance does not change. A good withdrawal prints balance B.
Constraints
- 1 <= commands <= 10^4
- 1 <= amount <= 10^6
Examples
Input
deposit 100 withdraw 130
Output
balance 100 error: short by 30
Solutions
A custom exception is a normal class that extends Exception (checked in Java) or Error/Exception in other languages. Extra fields let the catch block act on data, not on the message text. The failed withdrawal leaves the balance unchanged because the check happens before the change.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One result per command.
* Approach: Own exception class.
* Time : O(n)
* Space : O(1)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: Our own checked exception. It carries the missing amount as extra data.
static class InsufficientFundsException extends Exception {
private final long missing;
InsufficientFundsException(long missing) {
super("short by " + missing);
this.missing = missing;
}
long getMissing() {
return missing;
}
}
static class Account {
private long balance = 0;
long deposit(long amount) {
balance += amount;
return balance;
}
// Step 2: "throws" tells the caller that this method can fail. The caller must handle it.
long withdraw(long amount) throws InsufficientFundsException {
if (amount > balance) {
throw new InsufficientFundsException(amount - balance);
}
balance -= amount;
return balance;
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
Account account = new Account();
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
String[] part = lines[i].split(" ");
long amount = Long.parseLong(part[1]);
// Step 3: Catch our own exception and read the data it carries.
try {
long balance = part[0].equals("deposit") ? account.deposit(amount) : account.withdraw(amount);
output[i] = "balance " + balance;
} catch (InsufficientFundsException error) {
output[i] = "error: short by " + error.getMissing();
}
}
return output;
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
java.util.List<String> all = new java.util.ArrayList<>();
while (scanner.hasNextLine()) {
String line = scanner.nextLine().trim();
if (!line.isEmpty()) {
all.add(line);
}
}
String[] lines = all.toArray(new String[0]);
System.out.println(String.join("\n", solve(lines)));
}
}
Hints (1)
- Why is a field better than parsing the message?