{ }codelper
스택P0348

급식실 식판 더미

급식실에 식판을 쌓아 두는 더미가 하나 있고, 처음에는 비어 있다. 식판에는 번호가 적혀 있고, 같은 번호의 식판이 여러 개 있을 수 있다. 명령 q개가 차례로 주어진다. put x는 번호 x인 식판 하나를 더미의 맨 위에 올린다. take c는 학생 c명이 차례로 더미의 맨 위 식판을 하나씩 가져간다. 더미에 식판이 c개보다 적게 있으면 있는 만큼만 가져가고, 나머지 학생은 식판 없이 돌아간다. take 명령마다 가져간 식판의 번호를 가져간 차례대로 빈칸 하나로 띄워 한 줄에 출력하라. 식판을 하나도 가져가지 못했으면 그 줄에 -를 출력하라. 명령을 모두 처리한 뒤 마지막 줄에 더미에 남은 식판의 번호를 맨 위부터 아래로 차례대로 빈칸 하나로 띄워 출력하라. 남은 식판이 없으면 마지막 줄에 -를 출력하라.

입력
첫 줄에 q(1 ≤ q ≤ 9,000), 다음 q줄에 명령이 한 줄에 하나씩 주어진다.
1 ≤ x ≤ 1,000,000, 1 ≤ c ≤ 9,000(모두 정수이고 쉼표 없이 숫자만 주어진다).
명령의 낱말과 수는 빈칸 하나로 띄운다
출력
take 명령마다 한 줄, 그리고 마지막 줄에 남은 식판(번호는 쉼표 없이 숫자만)
예시 1 · stdin
8
put 3
put 7
put 5
take 2
take 3
take 1
put 4
put 9
stdout
5 7
3
-
9 4
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

맨 위에 올리고 맨 위에서 꺼내는 스택은 언어마다 쓰는 것이 달라요.
Python은 리스트의 append·pop(), JS·TS는 배열의 push·pop()을 써서 끝이 맨 위가 돼요.
Java는 ArrayDeque의 push·pop, C#은 Stack<int>의 Push·Pop을 써요.
C++의 std::stack은 속을 돌 수 없어서 마지막 줄을 쓰려면 vector의 push_back·pop_back을 써요.
C는 배열과 맨 위 자리를 가리키는 수 하나로 만들어요.
크레이콘은 목록에 넣기로 올리고 자리빼기(개수 - 1)로 꺼내요.
함정 하나: 빈 스택에서 꺼낼 때 일어나는 일이 달라요.
Python의 pop()은 IndexError로, Java의 ArrayDeque.pop()은 NoSuchElementException으로, C#의 Pop()은 InvalidOperationException으로 멈춰요.
예시의 take 3은 식판이 하나뿐일 때 오므로, 비었는지 묻지 않고 세 번 꺼내면 거기서 멈춰요.
C++의 빈 vector에 pop_back을 하는 것과 C에서 맨 위 자리가 0보다 작아지는 것은 무슨 일이 생길지 정해져 있지 않아요.
함정 둘: JS의 pop()은 빈 배열에서도 오류 없이 undefined를 줘요.
그것까지 담으면 꺼낸 것이 없어도 목록이 비어 있지 않아서, 예시의 take 1이 - 대신 빈 줄을 출력해요(join은 undefined를 빈 문자열로 써요).
TS에서는 pop()의 타입이 number | undefined라서 number[]에 바로 담으면 타입 오류로 알려 줘요.
함정 셋: Python에서 pile[-c:]로 한 번에 잘라 내면 편하지만 조각은 아래쪽부터 나와요.
예시의 첫 줄이 5 7이 아니라 7 5가 돼요.
함정 넷: 스택을 처음부터 끝까지 돌 때의 차례도 달라요.
Java의 ArrayDeque와 C#의 Stack<int>는 맨 위부터 돌지만, Java의 옛 Stack 클래스는 맨 아래부터 돌아서 예시의 마지막 줄이 4 9가 돼요.
Python 리스트, JS 배열, C++ vector, 크레이콘 목록도 맨 아래부터이므로 거꾸로 돌거나 뒤집어야 해요(reversed(pile), pile.reverse(), rbegin(), 뒤집기()).

Pythonmain.py · 18 줄
import sys lines = sys.stdin.read().split("\n")q = int(lines[0])pile = []  # 리스트의 끝이 더미의 맨 위out = []for i in range(1, q + 1):    cmd, v = lines[i].split()    v = int(v)    if cmd == "put":        pile.append(v)    else:        taken = []        while len(taken) < v and pile:  # 비었는지 먼저 묻고 꺼낸다            taken.append(pile.pop())        out.append(" ".join(map(str, taken)) if taken else "-")out.append(" ".join(map(str, reversed(pile))) if pile else "-")  # 맨 위부터print("\n".join(out))
JavaScriptmain.js · 18 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const q = Number(lines[0]);const pile = []; // 배열의 끝이 더미의 맨 위const out = [];for (let i = 1; i <= q; i++) {  const [cmd, t] = lines[i].split(" ");  const v = Number(t);  if (cmd === "put") {    pile.push(v);  } else {    const taken = [];    // 비었는지 먼저 묻고 꺼낸다(빈 배열의 pop()은 오류 없이 undefined를 준다)    while (taken.length < v && pile.length > 0) taken.push(pile.pop());    out.push(taken.length > 0 ? taken.join(" ") : "-");  }}out.push(pile.length > 0 ? pile.reverse().join(" ") : "-"); // 맨 위부터console.log(out.join("\n"));
TypeScriptmain.ts · 24 줄
import { readFileSync } from "node:fs"; const lines: string[] = readFileSync(0, "utf8").split("\n");const q: number = Number(lines[0]);const pile: number[] = []; // 배열의 끝이 더미의 맨 위const out: string[] = [];for (let i = 1; i <= q; i++) {  const [cmd, t] = lines[i].split(" ");  const v: number = Number(t);  if (cmd === "put") {    pile.push(v);  } else {    const taken: number[] = [];    // pop()의 타입은 number | undefined: 비었는지 먼저 묻고 꺼낸다    while (taken.length < v) {      const top: number | undefined = pile.pop();      if (top === undefined) break;      taken.push(top);    }    out.push(taken.length > 0 ? taken.join(" ") : "-");  }}out.push(pile.length > 0 ? pile.reverse().join(" ") : "-"); // 맨 위부터console.log(out.join("\n"));
JavaMain.java · 41 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayDeque;import java.util.Deque; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int q = Integer.parseInt(br.readLine().trim());        Deque<Integer> pile = new ArrayDeque<>(); // push·pop이 맨 위에서 일어난다        StringBuilder sb = new StringBuilder();        for (int i = 0; i < q; i++) {            String[] parts = br.readLine().split(" ");            int v = Integer.parseInt(parts[1]);            if (parts[0].equals("put")) {                pile.push(v);            } else {                int count = 0;                while (count < v && !pile.isEmpty()) { // 비었는지 먼저 묻고 꺼낸다                    if (count > 0) sb.append(' ');                    sb.append(pile.pop());                    count++;                }                if (count == 0) sb.append('-');                sb.append('\n');            }        }        if (pile.isEmpty()) {            sb.append('-');        } else {            boolean first = true;            for (int x : pile) { // ArrayDeque는 맨 위부터 돈다                if (!first) sb.append(' ');                sb.append(x);                first = false;            }        }        System.out.println(sb);    }}
C#Main.cs · 37 줄
using System;using System.Collections.Generic;using System.Text; class Program{    static void Main()    {        int q = int.Parse(Console.ReadLine()!);        var pile = new Stack<int>();        var sb = new StringBuilder();        for (int i = 0; i < q; i++)        {            string[] parts = Console.ReadLine()!.Split(' ');            int v = int.Parse(parts[1]);            if (parts[0] == "put")            {                pile.Push(v);            }            else            {                int count = 0;                while (count < v && pile.Count > 0) // 비었는지 먼저 묻고 꺼낸다                {                    if (count > 0) sb.Append(' ');                    sb.Append(pile.Pop());                    count++;                }                if (count == 0) sb.Append('-');                sb.Append('\n');            }        }        // Stack<T>는 맨 위부터 돈다        sb.Append(pile.Count > 0 ? string.Join(" ", pile) : "-");        Console.WriteLine(sb);    }}
C++main.cpp · 37 줄
#include <iostream>#include <string>#include <vector>using namespace std; int main() {    ios::sync_with_stdio(false);    cin.tie(nullptr);    int q;    cin >> q;    vector<int> pile; // std::stack은 속을 돌 수 없어서 vector를 스택으로 쓴다(끝이 맨 위)    for (int i = 0; i < q; i++) {        string cmd;        int v;        cin >> cmd >> v;        if (cmd == "put") {            pile.push_back(v);        } else {            int count = 0;            while (count < v && !pile.empty()) { // 비었는지 먼저 묻고 꺼낸다                if (count > 0) cout << ' ';                cout << pile.back();                pile.pop_back();                count++;            }            if (count == 0) cout << '-';            cout << '\n';        }    }    if (pile.empty()) cout << '-';    for (auto it = pile.rbegin(); it != pile.rend(); ++it) { // 맨 위부터        if (it != pile.rbegin()) cout << ' ';        cout << *it;    }    cout << '\n';    return 0;}
Cmain.c · 33 줄
#include <stdio.h>#include <string.h> int pile[9000]; /* pile[top - 1]이 더미의 맨 위 */ int main(void) {    int q, top = 0;    if (scanf("%d", &q) != 1) return 0;    for (int i = 0; i < q; i++) {        char cmd[8];        int v;        if (scanf("%7s %d", cmd, &v) != 2) return 0;        if (strcmp(cmd, "put") == 0) {            pile[top++] = v;        } else {            int count = 0;            while (count < v && top > 0) { /* 비었는지 먼저 묻고 꺼낸다 */                if (count > 0) printf(" ");                printf("%d", pile[--top]);                count++;            }            if (count == 0) printf("-");            printf("\n");        }    }    if (top == 0) printf("-");    for (int i = top - 1; i >= 0; i--) { /* 맨 위부터 */        printf("%d", pile[i]);        if (i > 0) printf(" ");    }    printf("\n");    return 0;}
Craykonmain.cray · 37 줄
q = 콘솔.줄읽기().수로변환();pile = []; // 목록의 끝이 더미의 맨 위반복 (i = 0; i < q; i++){    parts = 콘솔.줄읽기().나누기();    v = parts[1].수로변환();    만약 (parts[0] == "put")    {        pile.넣기(v);    }    아니면    {        taken = [];        동안 (taken.개수 < v && pile.개수 > 0)        {            taken.넣기(pile[pile.개수 - 1]);            pile.자리빼기(pile.개수 - 1);        }        만약 (taken.개수 == 0)        {            콘솔.쓰기("-");        }        아니면        {            콘솔.쓰기(taken.잇기(" "));        }    }}만약 (pile.개수 == 0){    콘솔.쓰기("-");}아니면{    pile.뒤집기(); // 맨 위부터    콘솔.쓰기(pile.잇기(" "));}