Simulate a cash machine used with one card.
The first line gives the account balance B, the four-digit PIN P and the machine's cash M, separated by single spaces.
P may start with 0 (for example 0123).
From the second line on, commands are given one per line, and the run ends at the command quit.
Lines after quit, if any, are not processed.
The machine is in one of three states: idle (no card), card (a card is in but the PIN has not been entered correctly yet) and ready (the PIN was correct); it starts idle.
The machine remembers how many times the PIN was wrong.
This count carries over when the card is taken out and put in again, and becomes 0 when the PIN is correct.
Process each command as follows and print one line.
insert: if the card has been retained, "blocked". Otherwise, if the state is not idle, "error". Otherwise set the state to card and print "card in".
pin x: if the state is not card, "error" (this does not count as wrong). If x is exactly the same text as P, set the state to ready and the wrong count to 0 and print "ok". Otherwise add 1 to the wrong count. If the count becomes 3, the machine retains the card, sets the state to idle and prints "retained"; otherwise "wrong".
withdraw n: if the state is not ready, "error". If n is greater than the balance, "insufficient". Otherwise, if n is greater than the machine's cash, "no cash". Otherwise subtract n from both the balance and the machine's cash and print the new balance.
deposit n: if the state is not ready, "error". Otherwise add n to both the balance and the machine's cash and print the new balance.
balance: if the state is not ready, "error"; otherwise print the balance.
eject: if the state is idle, "error". Otherwise set the state to idle and print "card out".
At quit, print the balance and the machine's cash on a last line, separated by a single space.
Input
0 ≤ B ≤ 10^9, 0 ≤ M ≤ 10^9, P is four digits, 1 to 1,000 command lines up to and including quit, and quit always appears, x in pin has 1 to 6 digits, 1 ≤ n ≤ 10^6
Output
one line for each command before quit, then one line with the balance and cash
error
card in
wrong
wrong
card out
card in
retained
blocked
50000 30000
main.py
Error List00F8 ↓ · ⇧F8 ↑
Input (stdin)
When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).
$ Ready
Open this on a computer to write and run code. On mobile you can read the problem and the solutions.
In other languagesShow solutions by language · 8 languages
This loop reads until the end marker quit: read one line, then while (cmd != "quit") { handle; read the next line }. Reading to the end of input (EOF) instead also handles the lines after quit (the last insert in the first example) and changes the answer. You branch on the command first and then ask about the state and the values inside it: nested conditions. The order of the inner checks is part of the rules, so asking about missing cash before the balance in withdraw changes the answer when both are short. Compare the PIN as a string. Turning it into a number makes 0123 equal to 123, so pin 123 in the second example would be accepted. String equality is == in Python, C#, JS, TS and C++ (std::string), equals in Java (== checks for the same object), and strcmp(a, b) == 0 in C. In C, a == b compares the arrays' addresses and is always false. The state names can be C enum { IDLE, CARD, READY }, a C++ enum class, or string constants elsewhere. Craykon loops with while (p[0] != "quit") and branches with if … else if … else. Another common mistake is resetting the wrong count to 0 on every insert (in the second example one more wrong PIN after re-inserting is enough to retain the card).
Pythonmain.py · 69 lines
import sysfirst = sys.stdin.readline().split()balance, pin, cash = int(first[0]), first[1], int(first[2]) # PIN은 0으로 시작할 수 있어 문자열로 둔다state = "idle" # idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨)wrong = 0 # 틀린 횟수: 카드를 뺐다 넣어도 이어진다retained = False # 세 번 틀려 기계가 카드를 가져갔나out = []line = sys.stdin.readline().split()while line[0] != "quit": # quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 cmd = line[0] if cmd == "insert": if retained: out.append("blocked") elif state != "idle": out.append("error") else: state = "card" out.append("card in") elif cmd == "pin": if state != "card": out.append("error") elif line[1] == pin: state = "ready" wrong = 0 out.append("ok") else: wrong += 1 if wrong == 3: retained = True state = "idle" out.append("retained") else: out.append("wrong") elif cmd == "withdraw": n = int(line[1]) if state != "ready": out.append("error") elif n > balance: out.append("insufficient") elif n > cash: out.append("no cash") else: balance -= n cash -= n out.append(str(balance)) elif cmd == "deposit": if state != "ready": out.append("error") else: n = int(line[1]) balance += n cash += n out.append(str(balance)) elif cmd == "balance": if state != "ready": out.append("error") else: out.append(str(balance)) else: # eject if state == "idle": out.append("error") else: state = "idle" out.append("card out") line = sys.stdin.readline().split()out.append(f"{balance} {cash}")print("\n".join(out))
JavaScriptmain.js · 69 lines
const lines = require("fs").readFileSync(0, "utf8").split("\n");const first = lines[0].trim().split(/\s+/);let balance = Number(first[0]);const pin = first[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다let cash = Number(first[2]);let state = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨)let wrong = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다let retained = false; // 세 번 틀려 기계가 카드를 가져갔나const out = [];let i = 1;let p = lines[i].trim().split(/\s+/);while (p[0] !== "quit") { // quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 const cmd = p[0]; if (cmd === "insert") { if (retained) out.push("blocked"); else if (state !== "idle") out.push("error"); else { state = "card"; out.push("card in"); } } else if (cmd === "pin") { if (state !== "card") out.push("error"); else if (p[1] === pin) { state = "ready"; wrong = 0; out.push("ok"); } else { wrong++; if (wrong === 3) { retained = true; state = "idle"; out.push("retained"); } else { out.push("wrong"); } } } else if (cmd === "withdraw") { const n = Number(p[1]); if (state !== "ready") out.push("error"); else if (n > balance) out.push("insufficient"); else if (n > cash) out.push("no cash"); else { balance -= n; cash -= n; out.push(String(balance)); } } else if (cmd === "deposit") { if (state !== "ready") out.push("error"); else { const n = Number(p[1]); balance += n; cash += n; out.push(String(balance)); } } else if (cmd === "balance") { out.push(state !== "ready" ? "error" : String(balance)); } else { // eject if (state === "idle") out.push("error"); else { state = "idle"; out.push("card out"); } } i++; p = lines[i].trim().split(/\s+/);}out.push(`${balance} ${cash}`);console.log(out.join("\n"));
TypeScriptmain.ts · 70 lines
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const first: string[] = lines[0].trim().split(/\s+/);let balance: number = Number(first[0]);const pin: string = first[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다let cash: number = Number(first[2]);let state: string = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨)let wrong = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다let retained = false; // 세 번 틀려 기계가 카드를 가져갔나const out: string[] = [];let i = 1;let p: string[] = lines[i].trim().split(/\s+/);while (p[0] !== "quit") { // quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 const cmd = p[0]; if (cmd === "insert") { if (retained) out.push("blocked"); else if (state !== "idle") out.push("error"); else { state = "card"; out.push("card in"); } } else if (cmd === "pin") { if (state !== "card") out.push("error"); else if (p[1] === pin) { state = "ready"; wrong = 0; out.push("ok"); } else { wrong++; if (wrong === 3) { retained = true; state = "idle"; out.push("retained"); } else { out.push("wrong"); } } } else if (cmd === "withdraw") { const n: number = Number(p[1]); if (state !== "ready") out.push("error"); else if (n > balance) out.push("insufficient"); else if (n > cash) out.push("no cash"); else { balance -= n; cash -= n; out.push(String(balance)); } } else if (cmd === "deposit") { if (state !== "ready") out.push("error"); else { const n: number = Number(p[1]); balance += n; cash += n; out.push(String(balance)); } } else if (cmd === "balance") { out.push(state !== "ready" ? "error" : String(balance)); } else { // eject if (state === "idle") out.push("error"); else { state = "idle"; out.push("card out"); } } i++; p = lines[i].trim().split(/\s+/);}out.push(`${balance} ${cash}`);console.log(out.join("\n"));
JavaMain.java · 76 lines
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;public class Main { public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); String[] first = br.readLine().trim().split("\\s+"); int balance = Integer.parseInt(first[0]); String pin = first[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다 int cash = Integer.parseInt(first[2]); String state = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨) int wrong = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다 boolean retained = false; // 세 번 틀려 기계가 카드를 가져갔나 StringBuilder out = new StringBuilder(); String[] p = br.readLine().trim().split("\\s+"); while (!p[0].equals("quit")) { // quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 String cmd = p[0]; if (cmd.equals("insert")) { if (retained) out.append("blocked\n"); else if (!state.equals("idle")) out.append("error\n"); else { state = "card"; out.append("card in\n"); } } else if (cmd.equals("pin")) { if (!state.equals("card")) out.append("error\n"); else if (p[1].equals(pin)) { state = "ready"; wrong = 0; out.append("ok\n"); } else { wrong++; if (wrong == 3) { retained = true; state = "idle"; out.append("retained\n"); } else { out.append("wrong\n"); } } } else if (cmd.equals("withdraw")) { int n = Integer.parseInt(p[1]); if (!state.equals("ready")) out.append("error\n"); else if (n > balance) out.append("insufficient\n"); else if (n > cash) out.append("no cash\n"); else { balance -= n; cash -= n; out.append(balance).append('\n'); } } else if (cmd.equals("deposit")) { if (!state.equals("ready")) out.append("error\n"); else { int n = Integer.parseInt(p[1]); balance += n; cash += n; out.append(balance).append('\n'); } } else if (cmd.equals("balance")) { if (!state.equals("ready")) out.append("error\n"); else out.append(balance).append('\n'); } else { // eject if (state.equals("idle")) out.append("error\n"); else { state = "idle"; out.append("card out\n"); } } p = br.readLine().trim().split("\\s+"); } out.append(balance).append(' ').append(cash).append('\n'); System.out.print(out); }}
C#Main.cs · 98 lines
using System;using System.Text;class Program{ static void Main() { string[] first = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int balance = int.Parse(first[0]); string pin = first[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다 int cash = int.Parse(first[2]); string state = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨) int wrong = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다 bool retained = false; // 세 번 틀려 기계가 카드를 가져갔나 var sb = new StringBuilder(); string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); while (p[0] != "quit") // quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 { string cmd = p[0]; if (cmd == "insert") { if (retained) sb.Append("blocked\n"); else if (state != "idle") sb.Append("error\n"); else { state = "card"; sb.Append("card in\n"); } } else if (cmd == "pin") { if (state != "card") sb.Append("error\n"); else if (p[1] == pin) { state = "ready"; wrong = 0; sb.Append("ok\n"); } else { wrong++; if (wrong == 3) { retained = true; state = "idle"; sb.Append("retained\n"); } else { sb.Append("wrong\n"); } } } else if (cmd == "withdraw") { int n = int.Parse(p[1]); if (state != "ready") sb.Append("error\n"); else if (n > balance) sb.Append("insufficient\n"); else if (n > cash) sb.Append("no cash\n"); else { balance -= n; cash -= n; sb.Append(balance).Append('\n'); } } else if (cmd == "deposit") { if (state != "ready") sb.Append("error\n"); else { int n = int.Parse(p[1]); balance += n; cash += n; sb.Append(balance).Append('\n'); } } else if (cmd == "balance") { if (state != "ready") sb.Append("error\n"); else sb.Append(balance).Append('\n'); } else // eject { if (state == "idle") sb.Append("error\n"); else { state = "idle"; sb.Append("card out\n"); } } p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); } sb.Append(balance).Append(' ').Append(cash).Append('\n'); Console.Write(sb); }}
C++main.cpp · 78 lines
#include <iostream>#include <sstream>#include <string>enum class State { Idle, Card, Ready }; // 카드 없음 → 카드 들어옴 → PIN 확인됨int main() { int balance, cash; std::string pin; // PIN은 0으로 시작할 수 있어 문자열로 둔다 std::cin >> balance >> pin >> cash; State state = State::Idle; int wrong = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다 bool retained = false; // 세 번 틀려 기계가 카드를 가져갔나 std::ostringstream out; std::string cmd; std::cin >> cmd; while (cmd != "quit") { // quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 if (cmd == "insert") { if (retained) out << "blocked\n"; else if (state != State::Idle) out << "error\n"; else { state = State::Card; out << "card in\n"; } } else if (cmd == "pin") { std::string guess; std::cin >> guess; if (state != State::Card) out << "error\n"; else if (guess == pin) { state = State::Ready; wrong = 0; out << "ok\n"; } else { wrong++; if (wrong == 3) { retained = true; state = State::Idle; out << "retained\n"; } else { out << "wrong\n"; } } } else if (cmd == "withdraw") { int n; std::cin >> n; if (state != State::Ready) out << "error\n"; else if (n > balance) out << "insufficient\n"; else if (n > cash) out << "no cash\n"; else { balance -= n; cash -= n; out << balance << '\n'; } } else if (cmd == "deposit") { int n; std::cin >> n; if (state != State::Ready) out << "error\n"; else { balance += n; cash += n; out << balance << '\n'; } } else if (cmd == "balance") { if (state != State::Ready) out << "error\n"; else out << balance << '\n'; } else { // eject if (state == State::Idle) out << "error\n"; else { state = State::Idle; out << "card out\n"; } } std::cin >> cmd; } out << balance << ' ' << cash << '\n'; std::cout << out.str();}
Cmain.c · 76 lines
#include <stdbool.h>#include <stdio.h>#include <stdlib.h>#include <string.h>enum { IDLE, CARD, READY }; /* 카드 없음 → 카드 들어옴 → PIN 확인됨 */int main(void) { int balance, cash; char pin[8]; /* PIN은 0으로 시작할 수 있어 문자열로 둔다 */ char line[64], cmd[16], arg[16]; if (!fgets(line, sizeof line, stdin)) return 0; sscanf(line, "%d %7s %d", &balance, pin, &cash); int state = IDLE; int wrong = 0; /* 틀린 횟수: 카드를 뺐다 넣어도 이어진다 */ bool retained = false; /* 세 번 틀려 기계가 카드를 가져갔나 */ while (fgets(line, sizeof line, stdin)) { arg[0] = '\0'; sscanf(line, "%15s %15s", cmd, arg); if (strcmp(cmd, "quit") == 0) break; /* quit이 끝 표시: 그 뒤의 줄은 읽지 않는다 */ if (strcmp(cmd, "insert") == 0) { if (retained) puts("blocked"); else if (state != IDLE) puts("error"); else { state = CARD; puts("card in"); } } else if (strcmp(cmd, "pin") == 0) { if (state != CARD) puts("error"); else if (strcmp(arg, pin) == 0) { state = READY; wrong = 0; puts("ok"); } else { wrong++; if (wrong == 3) { retained = true; state = IDLE; puts("retained"); } else { puts("wrong"); } } } else if (strcmp(cmd, "withdraw") == 0) { int n = atoi(arg); if (state != READY) puts("error"); else if (n > balance) puts("insufficient"); else if (n > cash) puts("no cash"); else { balance -= n; cash -= n; printf("%d\n", balance); } } else if (strcmp(cmd, "deposit") == 0) { if (state != READY) puts("error"); else { int n = atoi(arg); balance += n; cash += n; printf("%d\n", balance); } } else if (strcmp(cmd, "balance") == 0) { if (state != READY) puts("error"); else printf("%d\n", balance); } else { /* eject */ if (state == IDLE) puts("error"); else { state = IDLE; puts("card out"); } } } printf("%d %d\n", balance, cash); return 0;}
Craykonmain.cray · 117 lines
첫줄 = Console.ReadLine().Trim().Split();잔액 = 첫줄[0].ToNumber();비밀번호 = 첫줄[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다현금 = 첫줄[2].ToNumber();상태 = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨)틀린수 = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다가져감 = false; // 세 번 틀려 기계가 카드를 가져갔나p = Console.ReadLine().Trim().Split();while (p[0] != "quit"){ 명령 = p[0]; if (명령 == "insert") { if (가져감) { Console.WriteLine("blocked"); } else if (상태 != "idle") { Console.WriteLine("error"); } else { 상태 = "card"; Console.WriteLine("card in"); } } else if (명령 == "pin") { if (상태 != "card") { Console.WriteLine("error"); } else if (p[1] == 비밀번호) { 상태 = "ready"; 틀린수 = 0; Console.WriteLine("ok"); } else { 틀린수++; if (틀린수 == 3) { 가져감 = true; 상태 = "idle"; Console.WriteLine("retained"); } else { Console.WriteLine("wrong"); } } } else if (명령 == "withdraw") { n = p[1].ToNumber(); if (상태 != "ready") { Console.WriteLine("error"); } else if (n > 잔액) { Console.WriteLine("insufficient"); } else if (n > 현금) { Console.WriteLine("no cash"); } else { 잔액 -= n; 현금 -= n; Console.WriteLine(잔액); } } else if (명령 == "deposit") { if (상태 != "ready") { Console.WriteLine("error"); } else { n = p[1].ToNumber(); 잔액 += n; 현금 += n; Console.WriteLine(잔액); } } else if (명령 == "balance") { if (상태 != "ready") { Console.WriteLine("error"); } else { Console.WriteLine(잔액); } } else { if (상태 == "idle") { Console.WriteLine("error"); } else { 상태 = "idle"; Console.WriteLine("card out"); } } p = Console.ReadLine().Trim().Split();}Console.WriteLine(잔액 + " " + 현금);