{ }codelper
定数スコープ変数の宣言P0086

アトラクションの定員

定員 30 人のアトラクションがある。
最初は誰もいない。
定員 30 は定数にし、いま中にいる人数・これまでに入れた人数・帰した人数は関数の外に置いた変数で数えよ。
命令ごとにその変数を変える関数(in の処理、out の処理)を呼んで処理する。
- in k:k 人が並ぶ。
空き(30 − 中にいる人数)と k の小さいほうだけが入り、残りは帰す。
入った人数を出力する。
- out k:k 人が出てくる。
出た後に中にいる人数を出力する。
すべての命令が終わったら、これまでに入れた人数と帰した人数を空白一つで区切って一行に出力する。

入力
1 行目に n(1 ≤ n ≤ 1000)、続く n 行に in k または out k。
in は 1 ≤ k ≤ 100、out は 1 ≤ k ≤ そのとき中にいる人数
出力
命令ごとに 1 行、最後の行に "入れた人数 帰した人数"
例 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()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 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 です。
Craykon には定数がないので、変えないと約束した変数 定員 = 30; で置きます。
関数の外の変数も違います:Java・C# はクラスの外に変数を置けないので static フィールドで、C・C++ はファイルスコープのグローバル変数で、JS・TS は外側の let で置きます。
Python は関数の中で読むだけなら外の変数が見えますが、inside += a のように代入した瞬間にローカル変数になり、UnboundLocalError が出ます。
なので先に global inside を書きます。
Craykon は一番上で作った変数を関数の中でも同じ変数として使うので、中 = 中 + 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));    }}コンソール.書く(들어간수 + " " + 돌려보낸수);