{ }codelper
끝 표시까지 반복겹친 조건P0139

현금 인출기 상태 따라가기

카드 한 장을 쓰는 현금 인출기를 흉내 낸다. 첫 줄에 계좌 잔액 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
출력
quit 앞의 명령마다 한 줄, 마지막에 잔액과 현금 한 줄
예시 1 · stdin
100000 4821 50000
insert
pin 4821
withdraw 30000
withdraw 80000
withdraw 30000
deposit 15000
withdraw 30000
balance
eject
withdraw 1000
quit
insert
stdout
카드 들어옴
확인
70000
잔액 부족
현금 부족
85000
55000
55000
카드 나옴
잘못된 명령
55000 5000
예시 2 · stdin
50000 0123 30000
balance
insert
pin 123
pin 1230
eject
insert
pin 0000
insert
quit
stdout
잘못된 명령
카드 들어옴
틀림
틀림
카드 나옴
카드 들어옴
카드 보관
사용 정지
50000 30000
main.py
입력(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 sys first = 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 = 콘솔.줄읽기().공백제거().나누기();}콘솔.쓰기(잔액 + " " + 현금);