카드 한 장을 쓰는 현금 인출기를 흉내 낸다.
첫 줄에 계좌 잔액 B, 네 자리 비밀번호 P, 기계에 든 현금 M이 빈칸 하나씩을 사이에 두고 주어진다.
P는 0으로 시작할 수 있다(예: 0123).
둘째 줄부터 명령이 한 줄에 하나씩 주어지고, quit 명령이 나오면 끝난다.
quit 뒤에 줄이 더 있어도 처리하지 않는다.
기계의 상태는 idle(카드 없음), card(카드가 들어왔지만 비밀번호를 아직 맞히지 않음), ready(비밀번호를 맞힘) 셋 중 하나이고, 처음에는 idle이다.
기계는 비밀번호를 틀린 횟수를 기억한다.
이 횟수는 카드를 뺐다가 다시 넣어도 이어지고, 비밀번호를 맞히면 0이 된다.
명령마다 다음과 같이 처리하고 한 줄을 출력한다.
insert: 카드를 가져간 적이 있으면 "사용 정지"이다. 그렇지 않고 상태가 idle이 아니면 "잘못된 명령"이다. 그 밖에는 상태를 card로 바꾸고 "카드 들어옴"이다.
pin x: 상태가 card가 아니면 "잘못된 명령"이다(틀린 횟수에 들지 않는다). x가 P와 글자 그대로 같으면 상태를 ready로, 틀린 횟수를 0으로 바꾸고 "확인"이다. 다르면 틀린 횟수를 1 늘린다. 그 횟수가 3이 되면 기계가 카드를 가져가고 상태를 idle로 바꾸며 "카드 보관"이고, 아니면 "틀림"이다.
withdraw n: 상태가 ready가 아니면 "잘못된 명령"이다. n이 잔액보다 크면 "잔액 부족"이다. 그렇지 않고 n이 기계의 현금보다 크면 "현금 부족"이다. 그 밖에는 잔액과 기계의 현금에서 n씩 빼고 새 잔액을 출력한다.
deposit n: 상태가 ready가 아니면 "잘못된 명령"이다. 그 밖에는 잔액과 기계의 현금에 n씩 더하고 새 잔액을 출력한다.
balance: 상태가 ready가 아니면 "잘못된 명령"이고, 아니면 잔액을 출력한다.
eject: 상태가 idle이면 "잘못된 명령"이다. 그 밖에는 상태를 idle로 바꾸고 "카드 나옴"이다.
quit이 나오면 마지막 줄에 잔액과 기계의 현금을 빈칸 하나를 사이에 두고 출력한다.
입력
0 ≤ B ≤ 10^9, 0 ≤ M ≤ 10^9, P는 숫자 네 개, quit까지의 명령은 1 ~ 1,000줄(quit 포함)이고 quit은 반드시 나온다, pin의 x는 숫자 1 ~ 6개, 1 ≤ n ≤ 10^6
잘못된 명령
카드 들어옴
틀림
틀림
카드 나옴
카드 들어옴
카드 보관
사용 정지
50000 30000
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
quit이라는 끝 표시가 나올 때까지 읽는 반복이에요: 한 줄 읽고 while (cmd != "quit") { 처리; 다음 줄 읽기 }. 입력 끝(EOF)까지 읽어 버리면 quit 뒤의 줄(첫 예시의 마지막 insert)까지 처리해 답이 달라져요. 명령으로 먼저 가르고, 그 안에서 상태와 값을 다시 묻는 겹친 조건이에요. 안쪽 조건의 차례가 규칙이라 withdraw에서 현금 부족을 잔액 부족보다 먼저 물으면 둘 다 모자랄 때 답이 바뀌어요. 비밀번호는 문자열로 비교해요. 수로 바꾸면 0123과 123이 같아져서 두 번째 예시의 pin 123이 맞는 것으로 돼요. 문자열 같음은 Python·C#·JS·TS·C++ ==(std::string), Java는 equals(==는 같은 객체인지 비교), C는 strcmp(a, b) == 0이에요. C에서 a == b는 배열의 주소를 비교해서 늘 거짓이에요. 상태 이름은 C enum { IDLE, CARD, READY }, C++ enum class, 그 밖에는 문자열 상수로 둘 수 있어요. 크레이콘은 동안 (p[0] != "quit")으로 돌고 갈래는 만약 … 아니면 만약 … 아니면이에요. 틀린 횟수를 카드를 넣을 때마다 0으로 되돌리는 것도 흔한 실수예요(두 번째 예시는 뺐다 넣은 뒤 한 번만 더 틀려도 카드를 가져가요).
Pythonmain.py · 69 줄
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("사용 정지") elif state != "idle": out.append("잘못된 명령") else: state = "card" out.append("카드 들어옴") elif cmd == "pin": if state != "card": out.append("잘못된 명령") elif line[1] == pin: state = "ready" wrong = 0 out.append("확인") else: wrong += 1 if wrong == 3: retained = True state = "idle" out.append("카드 보관") else: out.append("틀림") elif cmd == "withdraw": n = int(line[1]) if state != "ready": out.append("잘못된 명령") elif n > balance: out.append("잔액 부족") elif n > cash: out.append("현금 부족") else: balance -= n cash -= n out.append(str(balance)) elif cmd == "deposit": if state != "ready": out.append("잘못된 명령") else: n = int(line[1]) balance += n cash += n out.append(str(balance)) elif cmd == "balance": if state != "ready": out.append("잘못된 명령") else: out.append(str(balance)) else: # eject if state == "idle": out.append("잘못된 명령") else: state = "idle" out.append("카드 나옴") line = sys.stdin.readline().split()out.append(f"{balance} {cash}")print("\n".join(out))
JavaScriptmain.js · 69 줄
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("사용 정지"); else if (state !== "idle") out.push("잘못된 명령"); else { state = "card"; out.push("카드 들어옴"); } } else if (cmd === "pin") { if (state !== "card") out.push("잘못된 명령"); else if (p[1] === pin) { state = "ready"; wrong = 0; out.push("확인"); } else { wrong++; if (wrong === 3) { retained = true; state = "idle"; out.push("카드 보관"); } else { out.push("틀림"); } } } else if (cmd === "withdraw") { const n = Number(p[1]); if (state !== "ready") out.push("잘못된 명령"); else if (n > balance) out.push("잔액 부족"); else if (n > cash) out.push("현금 부족"); else { balance -= n; cash -= n; out.push(String(balance)); } } else if (cmd === "deposit") { if (state !== "ready") out.push("잘못된 명령"); else { const n = Number(p[1]); balance += n; cash += n; out.push(String(balance)); } } else if (cmd === "balance") { out.push(state !== "ready" ? "잘못된 명령" : String(balance)); } else { // eject if (state === "idle") out.push("잘못된 명령"); else { state = "idle"; out.push("카드 나옴"); } } i++; p = lines[i].trim().split(/\s+/);}out.push(`${balance} ${cash}`);console.log(out.join("\n"));
TypeScriptmain.ts · 70 줄
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("사용 정지"); else if (state !== "idle") out.push("잘못된 명령"); else { state = "card"; out.push("카드 들어옴"); } } else if (cmd === "pin") { if (state !== "card") out.push("잘못된 명령"); else if (p[1] === pin) { state = "ready"; wrong = 0; out.push("확인"); } else { wrong++; if (wrong === 3) { retained = true; state = "idle"; out.push("카드 보관"); } else { out.push("틀림"); } } } else if (cmd === "withdraw") { const n: number = Number(p[1]); if (state !== "ready") out.push("잘못된 명령"); else if (n > balance) out.push("잔액 부족"); else if (n > cash) out.push("현금 부족"); else { balance -= n; cash -= n; out.push(String(balance)); } } else if (cmd === "deposit") { if (state !== "ready") out.push("잘못된 명령"); else { const n: number = Number(p[1]); balance += n; cash += n; out.push(String(balance)); } } else if (cmd === "balance") { out.push(state !== "ready" ? "잘못된 명령" : String(balance)); } else { // eject if (state === "idle") out.push("잘못된 명령"); else { state = "idle"; out.push("카드 나옴"); } } i++; p = lines[i].trim().split(/\s+/);}out.push(`${balance} ${cash}`);console.log(out.join("\n"));
JavaMain.java · 76 줄
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("사용 정지\n"); else if (!state.equals("idle")) out.append("잘못된 명령\n"); else { state = "card"; out.append("카드 들어옴\n"); } } else if (cmd.equals("pin")) { if (!state.equals("card")) out.append("잘못된 명령\n"); else if (p[1].equals(pin)) { state = "ready"; wrong = 0; out.append("확인\n"); } else { wrong++; if (wrong == 3) { retained = true; state = "idle"; out.append("카드 보관\n"); } else { out.append("틀림\n"); } } } else if (cmd.equals("withdraw")) { int n = Integer.parseInt(p[1]); if (!state.equals("ready")) out.append("잘못된 명령\n"); else if (n > balance) out.append("잔액 부족\n"); else if (n > cash) out.append("현금 부족\n"); else { balance -= n; cash -= n; out.append(balance).append('\n'); } } else if (cmd.equals("deposit")) { if (!state.equals("ready")) out.append("잘못된 명령\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("잘못된 명령\n"); else out.append(balance).append('\n'); } else { // eject if (state.equals("idle")) out.append("잘못된 명령\n"); else { state = "idle"; out.append("카드 나옴\n"); } } p = br.readLine().trim().split("\\s+"); } out.append(balance).append(' ').append(cash).append('\n'); System.out.print(out); }}
C#Main.cs · 98 줄
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("사용 정지\n"); else if (state != "idle") sb.Append("잘못된 명령\n"); else { state = "card"; sb.Append("카드 들어옴\n"); } } else if (cmd == "pin") { if (state != "card") sb.Append("잘못된 명령\n"); else if (p[1] == pin) { state = "ready"; wrong = 0; sb.Append("확인\n"); } else { wrong++; if (wrong == 3) { retained = true; state = "idle"; sb.Append("카드 보관\n"); } else { sb.Append("틀림\n"); } } } else if (cmd == "withdraw") { int n = int.Parse(p[1]); if (state != "ready") sb.Append("잘못된 명령\n"); else if (n > balance) sb.Append("잔액 부족\n"); else if (n > cash) sb.Append("현금 부족\n"); else { balance -= n; cash -= n; sb.Append(balance).Append('\n'); } } else if (cmd == "deposit") { if (state != "ready") sb.Append("잘못된 명령\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("잘못된 명령\n"); else sb.Append(balance).Append('\n'); } else // eject { if (state == "idle") sb.Append("잘못된 명령\n"); else { state = "idle"; sb.Append("카드 나옴\n"); } } p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); } sb.Append(balance).Append(' ').Append(cash).Append('\n'); Console.Write(sb); }}
C++main.cpp · 78 줄
#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 << "사용 정지\n"; else if (state != State::Idle) out << "잘못된 명령\n"; else { state = State::Card; out << "카드 들어옴\n"; } } else if (cmd == "pin") { std::string guess; std::cin >> guess; if (state != State::Card) out << "잘못된 명령\n"; else if (guess == pin) { state = State::Ready; wrong = 0; out << "확인\n"; } else { wrong++; if (wrong == 3) { retained = true; state = State::Idle; out << "카드 보관\n"; } else { out << "틀림\n"; } } } else if (cmd == "withdraw") { int n; std::cin >> n; if (state != State::Ready) out << "잘못된 명령\n"; else if (n > balance) out << "잔액 부족\n"; else if (n > cash) out << "현금 부족\n"; else { balance -= n; cash -= n; out << balance << '\n'; } } else if (cmd == "deposit") { int n; std::cin >> n; if (state != State::Ready) out << "잘못된 명령\n"; else { balance += n; cash += n; out << balance << '\n'; } } else if (cmd == "balance") { if (state != State::Ready) out << "잘못된 명령\n"; else out << balance << '\n'; } else { // eject if (state == State::Idle) out << "잘못된 명령\n"; else { state = State::Idle; out << "카드 나옴\n"; } } std::cin >> cmd; } out << balance << ' ' << cash << '\n'; std::cout << out.str();}
Cmain.c · 76 줄
#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("사용 정지"); else if (state != IDLE) puts("잘못된 명령"); else { state = CARD; puts("카드 들어옴"); } } else if (strcmp(cmd, "pin") == 0) { if (state != CARD) puts("잘못된 명령"); else if (strcmp(arg, pin) == 0) { state = READY; wrong = 0; puts("확인"); } else { wrong++; if (wrong == 3) { retained = true; state = IDLE; puts("카드 보관"); } else { puts("틀림"); } } } else if (strcmp(cmd, "withdraw") == 0) { int n = atoi(arg); if (state != READY) puts("잘못된 명령"); else if (n > balance) puts("잔액 부족"); else if (n > cash) puts("현금 부족"); else { balance -= n; cash -= n; printf("%d\n", balance); } } else if (strcmp(cmd, "deposit") == 0) { if (state != READY) puts("잘못된 명령"); else { int n = atoi(arg); balance += n; cash += n; printf("%d\n", balance); } } else if (strcmp(cmd, "balance") == 0) { if (state != READY) puts("잘못된 명령"); else printf("%d\n", balance); } else { /* eject */ if (state == IDLE) puts("잘못된 명령"); else { state = IDLE; puts("카드 나옴"); } } } printf("%d %d\n", balance, cash); return 0;}
Craykonmain.cray · 117 줄
첫줄 = 콘솔.줄읽기().공백제거().나누기();잔액 = 첫줄[0].수로변환();비밀번호 = 첫줄[1]; // PIN은 0으로 시작할 수 있어 문자열로 둔다현금 = 첫줄[2].수로변환();상태 = "idle"; // idle(카드 없음) → card(카드 들어옴) → ready(PIN 확인됨)틀린수 = 0; // 틀린 횟수: 카드를 뺐다 넣어도 이어진다가져감 = 거짓; // 세 번 틀려 기계가 카드를 가져갔나p = 콘솔.줄읽기().공백제거().나누기();동안 (p[0] != "quit"){ 명령 = p[0]; 만약 (명령 == "insert") { 만약 (가져감) { 콘솔.쓰기("사용 정지"); } 아니면 만약 (상태 != "idle") { 콘솔.쓰기("잘못된 명령"); } 아니면 { 상태 = "card"; 콘솔.쓰기("카드 들어옴"); } } 아니면 만약 (명령 == "pin") { 만약 (상태 != "card") { 콘솔.쓰기("잘못된 명령"); } 아니면 만약 (p[1] == 비밀번호) { 상태 = "ready"; 틀린수 = 0; 콘솔.쓰기("확인"); } 아니면 { 틀린수++; 만약 (틀린수 == 3) { 가져감 = 참; 상태 = "idle"; 콘솔.쓰기("카드 보관"); } 아니면 { 콘솔.쓰기("틀림"); } } } 아니면 만약 (명령 == "withdraw") { n = p[1].수로변환(); 만약 (상태 != "ready") { 콘솔.쓰기("잘못된 명령"); } 아니면 만약 (n > 잔액) { 콘솔.쓰기("잔액 부족"); } 아니면 만약 (n > 현금) { 콘솔.쓰기("현금 부족"); } 아니면 { 잔액 -= n; 현금 -= n; 콘솔.쓰기(잔액); } } 아니면 만약 (명령 == "deposit") { 만약 (상태 != "ready") { 콘솔.쓰기("잘못된 명령"); } 아니면 { n = p[1].수로변환(); 잔액 += n; 현금 += n; 콘솔.쓰기(잔액); } } 아니면 만약 (명령 == "balance") { 만약 (상태 != "ready") { 콘솔.쓰기("잘못된 명령"); } 아니면 { 콘솔.쓰기(잔액); } } 아니면 { 만약 (상태 == "idle") { 콘솔.쓰기("잘못된 명령"); } 아니면 { 상태 = "idle"; 콘솔.쓰기("카드 나옴"); } } p = 콘솔.줄읽기().공백제거().나누기();}콘솔.쓰기(잔액 + " " + 현금);