ATM Machine Simulator
Problem
Simulate an ATM. The account starts with balance 5000 and the correct PIN is 1234. Commands: pin X (a right PIN logs in and prints welcome; a wrong PIN prints wrong pin, N left, where N is the number of tries that remain out of 3; the third wrong PIN in a row locks the card and prints card locked; a locked card prints card locked for every later pin command, even with the right PIN; a right PIN resets the count of wrong tries). All other commands print login first when nobody is logged in. balance prints balance B. withdraw n needs a positive multiple of 100 (else invalid amount) and at most the balance (else insufficient funds); on success it prints the new balance as balance B. deposit n needs a positive amount (else invalid amount) and prints balance B. logout prints bye and logs out.
Constraints
- 1 <= commands <= 10^4
- |amounts| <= 10^9
Examples
Input
balance pin 1234 withdraw 1200 logout
Output
login first welcome balance 3800 bye
Solutions
The ATM is a small state machine with four pieces of state: balance, logged in, number of wrong tries and locked. Every rule is checked in a fixed order (lock, login, amount, funds), so two rules never fight over the answer. Real ATMs never keep PINs in code; this is only a model.
/*
* Problem : Process lines.
* Input : Several lines.
* Output : One answer per command.
* Approach: State in a class.
* Time : O(n)
* Space : O(1)
* Java : 8 or newer.
*/
import java.util.Scanner;
public class Main {
// Step 1: The ATM keeps its whole state in fields. Every command changes the state or reads it.
static class Atm {
private long balance = 5000;
private boolean loggedIn = false;
private int wrongTries = 0;
private boolean locked = false;
// Step 2: The PIN check follows the lock rule. A locked card never opens again.
String pin(String entered) {
if (locked) {
return "card locked";
}
if (entered.equals("1234")) {
loggedIn = true;
wrongTries = 0;
return "welcome";
}
wrongTries++;
if (wrongTries == 3) {
locked = true;
return "card locked";
}
return "wrong pin, " + (3 - wrongTries) + " left";
}
// Step 3: All other commands first check that someone is logged in.
String run(String[] part) {
if (!loggedIn) {
return "login first";
}
switch (part[0]) {
case "balance":
return "balance " + balance;
case "withdraw": {
long amount = Long.parseLong(part[1]);
if (amount <= 0 || amount % 100 != 0) {
return "invalid amount";
}
if (amount > balance) {
return "insufficient funds";
}
balance -= amount;
return "balance " + balance;
}
case "deposit": {
long amount = Long.parseLong(part[1]);
if (amount <= 0) {
return "invalid amount";
}
balance += amount;
return "balance " + balance;
}
default:
loggedIn = false;
return "bye";
}
}
}
// This method solves the task. It receives the input and returns the answer.
static String[] solve(String[] lines) {
Atm atm = new Atm();
String[] output = new String[lines.length];
for (int i = 0; i < lines.length; i++) {
String[] part = lines[i].split(" ");
output[i] = part[0].equals("pin") ? atm.pin(part[1]) : atm.run(part);
}
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 the lock check first in pin?