{ }codelper
클래스메서드P0079

함께 쓰는 번호표

창구 m개가 있는 가게를 창구 클래스로 만들어라.
번호표 일련번호는 모든 창구가 함께 쓰는 값 하나라서 클래스에 하나만 두고(클래스 변수·정적 필드), 창구마다 받은 번호표 목록은 각 창구 객체가 따로 갖는다.
창구는 1부터 m까지 번호가 붙은 서로 다른 객체 m개다.
첫 줄에 m과 명령 수 q, 다음 q줄에 명령이 하나씩 주어진다.
"take w": 일련번호를 1 늘려(처음 발급은 1) 그 번호표를 창구 w의 목록 끝에 넣고, "일련번호 목록길이"를 출력한다(목록길이는 넣은 뒤 창구 w의 목록에 있는 번호표 수).
"reset w": 창구 w의 목록만 비운다.
다른 창구와 일련번호는 그대로다.
출력은 없다.
"show w": 창구 w의 목록에 있는 번호표 수를 먼저 쓰고, 이어서 목록의 일련번호를 넣은 차례대로 빈칸 하나로 나누어 한 줄에 출력한다(비어 있으면 0만 출력).

입력
1 ≤ m ≤ 100, 1 ≤ q ≤ 5000, 1 ≤ w ≤ m
출력
take와 show 명령마다 한 줄
예시 1 · stdin
3 9
take 1
take 2
take 1
show 1
reset 1
show 1
take 1
show 1
show 3
stdout
1 1
2 1
3 2
2 1 3
0
4 1
1 4
0
main.py
입력(stdin)

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

$ 준비됐어요

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

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

이 문제는 클래스가 있는 Python·JavaScript·TypeScript·Java·C#·C++만 받아요(C에는 클래스가 없고, 크레이콘은 아직 클래스를 만들 수 없어요).
핵심은 "모든 객체가 함께 쓰는 값"과 "객체마다 따로인 값"을 가르는 거예요.
함께 쓰는 일련번호는 Java·C# static int, JS·TS static lastSerial = 0, C++ inline static int(C++17, inline이 없으면 클래스 밖에 int Window::lastSerial = 0; 정의가 따로 필요), Python은 클래스 몸통의 last_serial = 0이에요.
함정이 셋 있어요.
Python에서 self.last_serial += 1은 클래스 변수를 바꾸지 않고 그 객체에만 같은 이름의 새 값을 만들어서 창구마다 번호가 따로 세져요.
Window.last_serial += 1처럼 클래스 이름으로 바꾸세요.
반대로 served = []를 클래스 몸통에 두면 목록 하나를 모든 창구가 함께 써요.
객체마다 따로인 목록은 __init__ 안에서 self.served = []로 만들어요.
JS에서는 정적 필드를 this.lastSerial로 읽으면 객체에 없어서 undefined가 되고 NaN이 나와요(TS는 컴파일 오류로 막아 줘요).
마지막으로 객체를 m개 만들 때 Python [Window()] * m, JS Array(m).fill(new Window())는 객체 하나를 m칸이 함께 가리켜요.
Python [Window() for _ in range(m)], JS Array.from({ length: m }, () => new Window())처럼 칸마다 새로 만드세요.
C++ std::vector<Window> windows(m)은 값으로 m개를 따로 만들어서 괜찮아요.

Pythonmain.py · 35 줄
import sys  class Window:    last_serial = 0  # 클래스 변수: 모든 창구가 하나를 함께 쓴다     def __init__(self):        self.served = []  # 객체마다 따로 갖는 목록(여기서 만들어야 한다)     def take(self):        Window.last_serial += 1  # self.last_serial += 1 이면 이 창구만의 값이 새로 생긴다        self.served.append(Window.last_serial)        return Window.last_serial, len(self.served)     def reset(self):        self.served = []     def show(self):        return " ".join(map(str, [len(self.served)] + self.served))  data = sys.stdin.read().split()m, q = int(data[0]), int(data[1])windows = [Window() for _ in range(m)]out = []for i in range(q):    cmd, w = data[2 + 2 * i], windows[int(data[3 + 2 * i]) - 1]    if cmd == "take":        serial, local = w.take()        out.append(f"{serial} {local}")    elif cmd == "reset":        w.reset()    else:        out.append(w.show())print("\n".join(out))
JavaScriptmain.js · 35 줄
class Window {  static lastSerial = 0; // 정적 필드: 모든 창구가 하나를 함께 쓴다   constructor() {    this.served = []; // 객체마다 따로 갖는 목록  }   take() {    Window.lastSerial++; // this.lastSerial 은 객체에 없어서 undefined    this.served.push(Window.lastSerial);    return `${Window.lastSerial} ${this.served.length}`;  }   reset() {    this.served = [];  }   show() {    return [this.served.length, ...this.served].join(" ");  }} const data = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const m = Number(data[0]);const q = Number(data[1]);const windows = Array.from({ length: m }, () => new Window());const out = [];for (let i = 0; i < q; i++) {  const cmd = data[2 + 2 * i];  const w = windows[Number(data[3 + 2 * i]) - 1];  if (cmd === "take") out.push(w.take());  else if (cmd === "reset") w.reset();  else out.push(w.show());}console.log(out.join("\n"));
TypeScriptmain.ts · 34 줄
import { readFileSync } from "node:fs"; class Window {  private static lastSerial = 0; // 정적 필드: 모든 창구가 하나를 함께 쓴다  private served: number[] = []; // 객체마다 따로 갖는 목록   take(): string {    Window.lastSerial++;    this.served.push(Window.lastSerial);    return `${Window.lastSerial} ${this.served.length}`;  }   reset(): void {    this.served = [];  }   show(): string {    return [this.served.length, ...this.served].join(" ");  }} const data: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const m: number = Number(data[0]);const q: number = Number(data[1]);const windows: Window[] = Array.from({ length: m }, () => new Window());const out: string[] = [];for (let i = 0; i < q; i++) {  const cmd = data[2 + 2 * i];  const w = windows[Number(data[3 + 2 * i]) - 1];  if (cmd === "take") out.push(w.take());  else if (cmd === "reset") w.reset();  else out.push(w.show());}console.log(out.join("\n"));
JavaMain.java · 49 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import java.util.StringTokenizer; class Window {    private static int lastSerial = 0; // static: 모든 창구가 하나를 함께 쓴다    private List<Integer> served = new ArrayList<>(); // 객체마다 따로     String take() {        lastSerial++;        served.add(lastSerial);        return lastSerial + " " + served.size();    }     void reset() { served = new ArrayList<>(); }     String show() {        StringBuilder sb = new StringBuilder().append(served.size());        for (int s : served) sb.append(' ').append(s);        return sb.toString();    }} public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        StringTokenizer st = new StringTokenizer(in.readLine());        int m = Integer.parseInt(st.nextToken());        int q = Integer.parseInt(st.nextToken());        Window[] windows = new Window[m];        for (int i = 0; i < m; i++) windows[i] = new Window();         StringBuilder out = new StringBuilder();        for (int i = 0; i < q; i++) {            st = new StringTokenizer(in.readLine());            String cmd = st.nextToken();            Window w = windows[Integer.parseInt(st.nextToken()) - 1];            switch (cmd) {                case "take" -> out.append(w.take()).append('\n');                case "reset" -> w.reset();                default -> out.append(w.show()).append('\n');            }        }        System.out.print(out);    }}
C#Main.cs · 45 줄
using System;using System.Collections.Generic;using System.Text; class Window{    private static int lastSerial = 0; // static: 모든 창구가 하나를 함께 쓴다    private List<int> served = new List<int>(); // 객체마다 따로     public string Take()    {        lastSerial++;        served.Add(lastSerial);        return $"{lastSerial} {served.Count}";    }     public void Reset() => served = new List<int>();     public string Show() => served.Count == 0 ? "0" : $"{served.Count} {string.Join(" ", served)}";} class Program{    static void Main()    {        string[] first = Console.ReadLine().Split(' ');        int m = int.Parse(first[0]), q = int.Parse(first[1]);        var windows = new Window[m];        for (int i = 0; i < m; i++) windows[i] = new Window();         var sb = new StringBuilder();        for (int i = 0; i < q; i++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            Window w = windows[int.Parse(p[1]) - 1];            switch (p[0])            {                case "take": sb.Append(w.Take()).Append('\n'); break;                case "reset": w.Reset(); break;                default: sb.Append(w.Show()).Append('\n'); break;            }        }        Console.Write(sb);    }}
C++main.cpp · 40 줄
#include <iostream>#include <string>#include <vector> class Window {public:    std::string take() {        lastSerial++;        served_.push_back(lastSerial);        return std::to_string(lastSerial) + " " + std::to_string(served_.size());    }     void reset() { served_.clear(); }     std::string show() const {        std::string s = std::to_string(served_.size());        for (int x : served_) s += " " + std::to_string(x);        return s;    } private:    inline static int lastSerial = 0; // static: 모든 창구가 하나를 함께 쓴다(inline 없으면 클래스 밖에 정의가 필요)    std::vector<int> served_;          // 객체마다 따로}; int main() {    std::ios::sync_with_stdio(false);    int m, q;    std::cin >> m >> q;    std::vector<Window> windows(m); // 서로 다른 Window 객체 m개    for (int i = 0; i < q; i++) {        std::string cmd;        int w;        std::cin >> cmd >> w;        Window& win = windows[w - 1];        if (cmd == "take") std::cout << win.take() << '\n';        else if (cmd == "reset") win.reset();        else std::cout << win.show() << '\n';    }}