{ }codelper
상수변수 범위변수 만들기P0086

놀이기구 정원

정원이 30명인 놀이기구가 있다.
처음에는 아무도 없다.
정원 30은 상수로 두고, 지금 안에 있는 사람 수·지금까지 들여보낸 사람 수·돌려보낸 사람 수는 함수 밖에 둔 변수로 세어라.
명령마다 그 변수를 고치는 함수(in 처리, out 처리)를 불러 처리한다. - in k: k명이 줄을 선다.
빈자리 수(30 − 안에 있는 수)와 k 중 작은 만큼만 들어가고, 나머지는 돌려보낸다.
들어간 사람 수를 출력한다. - out k: k명이 나온다.
나온 뒤 안에 있는 사람 수를 출력한다. 모든 명령이 끝나면 지금까지 들여보낸 사람 수와 돌려보낸 사람 수를 빈칸 하나로 띄워 한 줄에 출력한다.

입력
첫 줄에 n(1 ≤ n ≤ 1000), 다음 n줄에 in k 또는 out k.
in은 1 ≤ k ≤ 100, out은 1 ≤ k ≤ 그때 안에 있는 사람 수
출력
명령마다 한 줄, 마지막 줄에 "들여보낸 수 돌려보낸 수"
예시 1 · stdin
6
in 12
in 25
out 10
in 4
out 20
in 40
stdout
12
18
20
4
4
26
60 21
main.py
입력(stdin)

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

$ 준비됐어요

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

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

상수 쓰는 법이 언어마다 달라요: Python은 CAPACITY = 30처럼 대문자로 이름만 짓고(바꿔도 막지 않아요, typing.Final은 검사 도구용), JS·TS const, Java static final int, C# const int, C #define CAPACITY 30(또는 const int, 다만 C에서는 배열 크기 같은 상수식이 아니에요), C++ constexpr int예요.
크레이콘에는 상수가 없어서 바꾸지 않기로 약속한 변수 정원 = 30;으로 둬요.
함수 밖 변수도 달라요: Java·C#은 클래스 밖에 변수를 둘 수 없어 static 필드로, C·C++은 파일 범위 전역 변수로, JS·TS는 바깥의 let으로 둬요.
Python은 함수 안에서 읽기만 하면 바깥 변수가 보이지만, inside += a처럼 넣는 순간 지역 변수가 되어 UnboundLocalError가 나요.
그래서 global inside를 먼저 적어요.
크레이콘은 맨 위에 만든 변수를 함수 안에서도 같은 변수로 써서 안 = 안 + a;가 바깥을 바꿔요.
다만 매개변수 이름을 들어가기(안, k)처럼 바깥 변수와 같게 지으면 함수 안의 안은 매개변수라서 바깥은 그대로예요.
흔한 함정 둘: 세는 값을 매개변수로 넘겨 함수 안에서 고치면 복사본만 바뀌고(C·Java·C#·JS·Python 모두 수는 값으로 넘겨요), 세는 변수를 반복문 안에서 만들면(for (...) { let inside = 0; ... }) 줄마다 0부터 다시 시작해요.

Pythonmain.py · 27 줄
CAPACITY = 30  # 상수: 대문자 이름은 '바꾸지 말자'는 약속일 뿐, Python이 막아 주지는 않는다 inside = 0       # 함수 밖(모듈)에 있는 변수 — 모든 함수가 같이 쓴다admitted = 0turned_away = 0  def enter(k):    global inside, admitted, turned_away  # 없으면 inside += ... 에서 UnboundLocalError    a = min(k, CAPACITY - inside)  # a는 이 함수 안에서만 있는 지역 변수    inside += a    admitted += a    turned_away += k - a    return a  def leave(k):    global inside    inside -= k    return inside  n = int(input())for _ in range(n):    cmd, k = input().split()    print(enter(int(k)) if cmd == "in" else leave(int(k)))print(admitted, turned_away)
JavaScriptmain.js · 28 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n"); const CAPACITY = 30; // const: 다시 넣으면 TypeErrorlet inside = 0; // 함수 밖의 let — 아래 함수들이 같이 쓴다let admitted = 0;let turnedAway = 0; function enter(k) {  const a = Math.min(k, CAPACITY - inside); // 함수 안의 const는 이 함수에서만 보인다  inside += a;  admitted += a;  turnedAway += k - a;  return a;} function leave(k) {  inside -= k;  return inside;} const n = Number(lines[0]);const out = [];for (let i = 1; i <= n; i++) {  const [cmd, k] = lines[i].trim().split(" ");  out.push(cmd === "in" ? enter(Number(k)) : leave(Number(k)));}out.push(`${admitted} ${turnedAway}`);console.log(out.join("\n"));
TypeScriptmain.ts · 29 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n"); const CAPACITY = 30; // 타입은 리터럴 30 — 다시 넣으면 컴파일 오류let inside = 0;let admitted = 0;let turnedAway = 0; function enter(k: number): number {  const a: number = Math.min(k, CAPACITY - inside);  inside += a;  admitted += a;  turnedAway += k - a;  return a;} function leave(k: number): number {  inside -= k;  return inside;} const n: number = Number(lines[0]);const out: (number | string)[] = [];for (let i = 1; i <= n; i++) {  const [cmd, k] = lines[i].trim().split(" ");  out.push(cmd === "in" ? enter(Number(k)) : leave(Number(k)));}out.push(`${admitted} ${turnedAway}`);console.log(out.join("\n"));
JavaMain.java · 36 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.IOException; public class Main {    static final int CAPACITY = 30; // final: 한 번 넣으면 못 바꾼다    static int inside = 0;          // static 필드 — 모든 static 메서드가 같이 쓴다    static int admitted = 0;    static int turnedAway = 0;     static int enter(int k) {        int a = Math.min(k, CAPACITY - inside); // 지역 변수        inside += a;        admitted += a;        turnedAway += k - a;        return a;    }     static int leave(int k) {        inside -= k;        return inside;    }     public static void main(String[] args) throws IOException {        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));        int n = Integer.parseInt(br.readLine().trim());        StringBuilder out = new StringBuilder();        for (int i = 0; i < n; i++) {            String[] parts = br.readLine().trim().split(" ");            int k = Integer.parseInt(parts[1]);            out.append(parts[0].equals("in") ? enter(k) : leave(k)).append('\n');        }        out.append(admitted).append(' ').append(turnedAway).append('\n');        System.out.print(out);    }}
C#Main.cs · 39 줄
using System;using System.Text; class Program{    const int Capacity = 30;  // const: 컴파일할 때 값이 박힌다    static int inside = 0;    // static 필드 — 클래스 안의 모든 메서드가 같이 쓴다    static int admitted = 0;    static int turnedAway = 0;     static int Enter(int k)    {        int a = Math.Min(k, Capacity - inside);        inside += a;        admitted += a;        turnedAway += k - a;        return a;    }     static int Leave(int k)    {        inside -= k;        return inside;    }     static void Main()    {        int n = int.Parse(Console.ReadLine());        var out_ = new StringBuilder();        for (int i = 0; i < n; i++)        {            string[] parts = Console.ReadLine().Trim().Split(' ');            int k = int.Parse(parts[1]);            out_.Append(parts[0] == "in" ? Enter(k) : Leave(k)).Append('\n');        }        out_.Append(admitted).Append(' ').Append(turnedAway).Append('\n');        Console.Write(out_);    }}
C++main.cpp · 34 줄
#include <algorithm>#include <iostream>#include <string> constexpr int CAPACITY = 30;  // constexpr: 컴파일할 때 정해지는 상수 int inside = 0;  // 전역 변수 — 아래 함수들이 같이 쓴다int admitted = 0;int turnedAway = 0; int enter(int k) {    int a = std::min(k, CAPACITY - inside);    inside += a;    admitted += a;    turnedAway += k - a;    return a;} int leave(int k) {    inside -= k;    return inside;} int main() {    int n;    std::cin >> n;    for (int i = 0; i < n; i++) {        std::string cmd;        int k;        std::cin >> cmd >> k;        std::cout << (cmd == "in" ? enter(k) : leave(k)) << '\n';    }    std::cout << admitted << ' ' << turnedAway << '\n';}
Cmain.c · 34 줄
#include <stdio.h>#include <string.h> #define CAPACITY 30  /* 전처리기가 글자 그대로 30으로 바꿔 넣는다 */ static int inside = 0;  /* 파일 범위 변수: 이 파일의 모든 함수가 같이 쓴다 */static int admitted = 0;static int turned_away = 0; int enter(int k) {    int room = CAPACITY - inside;    int a = k < room ? k : room;    inside += a;    admitted += a;    turned_away += k - a;    return a;} int leave(int k) {    inside -= k;    return inside;} int main(void) {    int n, k;    char cmd[4];    scanf("%d", &n);    for (int i = 0; i < n; i++) {        scanf("%3s %d", cmd, &k);        printf("%d\n", strcmp(cmd, "in") == 0 ? enter(k) : leave(k));    }    printf("%d %d\n", admitted, turned_away);    return 0;}
Craykonmain.cray · 37 줄
// 크레이콘에는 const가 없다: 바꾸지 않기로 약속한 변수로 둔다정원 = 30;안 = 0;들어간수 = 0;돌려보낸수 = 0; // 맨 위에 만든 변수는 함수 안에서도 같은 변수다(같이 쓴다)들어가기(k){    a = 수학.작은수(k, 정원 - 안);    안 = 안 + a;    들어간수 = 들어간수 + a;    돌려보낸수 = 돌려보낸수 + k - a;    돌려주기 a;} 나가기(k){    안 = 안 - k;    돌려주기 안;} n = 콘솔.줄읽기().수로변환();반복 (i = 0; i < n; i++){    parts = 콘솔.줄읽기().나누기();    k = parts[1].수로변환();    만약 (parts[0] == "in")    {        콘솔.쓰기(들어가기(k));    }    아니면    {        콘솔.쓰기(나가기(k));    }}콘솔.쓰기(들어간수 + " " + 돌려보낸수);