2 7
4 7
flipdone
until 1
flipdone
until 2
wait 5
flipdone
flip 2
stdout
2
4
1
7
1
2
4 0
0 7
main.py
エラー一覧00F8 ↓ · ⇧F8 ↑
入力(stdin)
実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。
$ 準備完了
コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。
ほかの言語では?言語別の解答を見る · 6 言語の解答
この問題はクラスのある Python・JavaScript・TypeScript・Java・C#・C++ だけを受け付けます(C にはクラスがなく、Craykon はまだクラスを作れません)。 メソッドはオブジェクトの中の値を読んだり変えたりする関数です。 Python は def run(self, seconds): のように最初の引数 self を自分で書き、JS・TS は run(seconds) { … } の中で this.top と書いて届きます。 Java・C#・C++ は top と書くだけでフィールドです。 C++ は値を変えないメソッドの後ろに const を付けます(bool isEmpty() const)。 ひっくり返すのは二つのフィールドの入れ替えで、Python は self.top, self.bottom = self.bottom, self.top、JS・TS は [this.top, this.bottom] = [this.bottom, this.top]、C# は (top, bottom) = (bottom, top)、C++ は std::swap(top_, bottom_) と 1 行で書き、Java は一時変数を一つ置きます。 落とし穴は六つ:① top = bottom; bottom = top; のように順に代入すると上の部屋の値が先に消え、二つの部屋が同じ数になります。 ② メソッドを呼ぶときにかっこを忘れること。 Python の if g.is_empty: と JavaScript の if (g.isEmpty) はエラーなしに動きますが、メソッドそのものはいつも真なので、空でない砂時計までひっくり返します(例の二つ目の flipdone が 1 ではなく 2 になります)。 TypeScript は「この条件は常に真」というエラー(TS2774)で、Java・C#・C++ はコンパイルエラーで知らせてくれます。 かっこなしで書きたければ Python @property、JS・TS get isEmpty()、C# のプロパティ bool IsEmpty => top == 0; にします。 ③ 流すときは min(seconds, top) だけ移します。 ただ top -= seconds と書くと上の部屋が負になります。 ④「今回空になったか」と「今空であるか」は違います。 流すメソッドが top == 0 を返すと、前から空だった砂時計まで数えます(例の wait 5 が 1 ではなく 2 になります)。 ⑤ until で流す時間はループの前に一度だけたずねて変数に入れます。 ループの中で g.run(target.remaining()) のようにたずね直すと、i 番が空になったあとは 0 になり、後ろの番号の砂時計は流れません。 ⑥ C++ の for (Hourglass g : glasses) は砂時計をコピーするので、コピーに時間が流れます。 Hourglass& g と書けば本物が変わります。 Python・JS・TS・Java・C# のループ変数は同じオブジェクトを指すので、そのまま変わります。
Pythonmain.py · 65 行
import sysclass Hourglass: def __init__(self, capacity): # 처음에는 모래가 전부 아래 칸에 있다 self.top = 0 self.bottom = capacity def flip(self): self.top, self.bottom = self.bottom, self.top def run(self, seconds): """seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 True를 돌려준다.""" moved = min(seconds, self.top) self.top -= moved self.bottom += moved return moved > 0 and self.top == 0 def is_empty(self): return self.top == 0 def remaining(self): return self.topdef main(): lines = sys.stdin.read().split("\n") n, q = map(int, lines[0].split()) glasses = [Hourglass(int(c)) for c in lines[1].split()] elapsed = 0 out = [] for line in lines[2:2 + q]: parts = line.split() cmd = parts[0] if cmd == "flip": glasses[int(parts[1]) - 1].flip() elif cmd == "wait": t = int(parts[1]) elapsed += t done = 0 for g in glasses: if g.run(t): done += 1 out.append(str(done)) elif cmd == "until": # 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) t = glasses[int(parts[1]) - 1].remaining() elapsed += t for g in glasses: g.run(t) out.append(str(elapsed)) else: # flipdone flipped = 0 for g in glasses: if g.is_empty(): # 괄호를 빼면 메서드 자체라 늘 참이다 g.flip() flipped += 1 out.append(str(flipped)) for g in glasses: out.append(f"{g.top} {g.bottom}") print("\n".join(out))main()
JavaScriptmain.js · 64 行
class Hourglass { constructor(capacity) { // 처음에는 모래가 전부 아래 칸에 있다 this.top = 0; this.bottom = capacity; } flip() { [this.top, this.bottom] = [this.bottom, this.top]; } // seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 true를 돌려준다 run(seconds) { const moved = Math.min(seconds, this.top); this.top -= moved; this.bottom += moved; return moved > 0 && this.top === 0; } isEmpty() { return this.top === 0; } remaining() { return this.top; }}const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, q] = lines[0].trim().split(" ").map(Number);const glasses = lines[1].trim().split(" ").slice(0, n).map((c) => new Hourglass(Number(c)));let elapsed = 0;const out = [];for (let k = 2; k < 2 + q; k++) { const [cmd, arg] = lines[k].trim().split(" "); if (cmd === "flip") { glasses[Number(arg) - 1].flip(); } else if (cmd === "wait") { const t = Number(arg); elapsed += t; let done = 0; for (const g of glasses) { if (g.run(t)) done++; } out.push(done); } else if (cmd === "until") { // 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) const t = glasses[Number(arg) - 1].remaining(); elapsed += t; for (const g of glasses) g.run(t); out.push(elapsed); } else { let flipped = 0; for (const g of glasses) { if (g.isEmpty()) { // 괄호를 빼면 함수 자체라 늘 참이다 g.flip(); flipped++; } } out.push(flipped); }}for (const g of glasses) out.push(`${g.top} ${g.bottom}`);console.log(out.join("\n"));
TypeScriptmain.ts · 68 行
import { readFileSync } from "node:fs";class Hourglass { private top = 0; // 처음에는 모래가 전부 아래 칸에 있다 constructor(private bottom: number) {} flip(): void { [this.top, this.bottom] = [this.bottom, this.top]; } // seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 true를 돌려준다 run(seconds: number): boolean { const moved = Math.min(seconds, this.top); this.top -= moved; this.bottom += moved; return moved > 0 && this.top === 0; } isEmpty(): boolean { return this.top === 0; } remaining(): number { return this.top; } describe(): string { return `${this.top} ${this.bottom}`; }}const lines: string[] = readFileSync(0, "utf8").split("\n");const [n, q] = lines[0].trim().split(" ").map(Number);const glasses: Hourglass[] = lines[1].trim().split(" ").slice(0, n).map((c) => new Hourglass(Number(c)));let elapsed = 0;const out: string[] = [];for (let k = 2; k < 2 + q; k++) { const [cmd, arg] = lines[k].trim().split(" "); if (cmd === "flip") { glasses[Number(arg) - 1].flip(); } else if (cmd === "wait") { const t = Number(arg); elapsed += t; let done = 0; for (const g of glasses) { if (g.run(t)) done++; } out.push(String(done)); } else if (cmd === "until") { // 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) const t = glasses[Number(arg) - 1].remaining(); elapsed += t; for (const g of glasses) g.run(t); out.push(String(elapsed)); } else { let flipped = 0; for (const g of glasses) { if (g.isEmpty()) { // 괄호를 빼면 TypeScript가 컴파일 오류로 알려 준다 g.flip(); flipped++; } } out.push(String(flipped)); }}for (const g of glasses) out.push(g.describe());console.log(out.join("\n"));
JavaMain.java · 83 行
import java.io.*;import java.util.*;public class Main { static class Hourglass { private int top = 0; // 처음에는 모래가 전부 아래 칸에 있다 private int bottom; Hourglass(int capacity) { this.bottom = capacity; } void flip() { int t = top; top = bottom; bottom = t; } // seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 true를 돌려준다 boolean run(int seconds) { int moved = Math.min(seconds, top); top -= moved; bottom += moved; return moved > 0 && top == 0; } boolean isEmpty() { return top == 0; } int remaining() { return top; } String describe() { return top + " " + bottom; } } public static void main(String[] args) throws IOException { BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(br.readLine()); int n = Integer.parseInt(st.nextToken()); int q = Integer.parseInt(st.nextToken()); st = new StringTokenizer(br.readLine()); Hourglass[] glasses = new Hourglass[n]; for (int i = 0; i < n; i++) glasses[i] = new Hourglass(Integer.parseInt(st.nextToken())); int elapsed = 0; StringBuilder sb = new StringBuilder(); for (int k = 0; k < q; k++) { st = new StringTokenizer(br.readLine()); String cmd = st.nextToken(); if (cmd.equals("flip")) { glasses[Integer.parseInt(st.nextToken()) - 1].flip(); } else if (cmd.equals("wait")) { int t = Integer.parseInt(st.nextToken()); elapsed += t; int done = 0; for (Hourglass g : glasses) { if (g.run(t)) done++; } sb.append(done).append('\n'); } else if (cmd.equals("until")) { // 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) int t = glasses[Integer.parseInt(st.nextToken()) - 1].remaining(); elapsed += t; for (Hourglass g : glasses) g.run(t); sb.append(elapsed).append('\n'); } else { int flipped = 0; for (Hourglass g : glasses) { if (g.isEmpty()) { g.flip(); flipped++; } } sb.append(flipped).append('\n'); } } for (Hourglass g : glasses) sb.append(g.describe()).append('\n'); System.out.print(sb); }}
C#Main.cs · 99 行
using System;using System.Linq;using System.Text;class Hourglass{ private int top = 0; // 처음에는 모래가 전부 아래 칸에 있다 private int bottom; public Hourglass(int capacity) { bottom = capacity; } public void Flip() { (top, bottom) = (bottom, top); } // seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 true를 돌려준다 public bool Run(int seconds) { int moved = Math.Min(seconds, top); top -= moved; bottom += moved; return moved > 0 && top == 0; } public bool IsEmpty() { return top == 0; } public int Remaining() { return top; } public string Describe() { return $"{top} {bottom}"; }}class Program{ static void Main() { int[] head = Console.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); int q = head[1]; Hourglass[] glasses = Console.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries) .Select(c => new Hourglass(int.Parse(c))).ToArray(); int elapsed = 0; var sb = new StringBuilder(); for (int k = 0; k < q; k++) { string[] parts = Console.ReadLine()!.Split(' ', StringSplitOptions.RemoveEmptyEntries); string cmd = parts[0]; if (cmd == "flip") { glasses[int.Parse(parts[1]) - 1].Flip(); } else if (cmd == "wait") { int t = int.Parse(parts[1]); elapsed += t; int done = 0; foreach (Hourglass g in glasses) { if (g.Run(t)) done++; } sb.Append(done).Append('\n'); } else if (cmd == "until") { // 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) int t = glasses[int.Parse(parts[1]) - 1].Remaining(); elapsed += t; foreach (Hourglass g in glasses) g.Run(t); sb.Append(elapsed).Append('\n'); } else { int flipped = 0; foreach (Hourglass g in glasses) { if (g.IsEmpty()) { g.Flip(); flipped++; } } sb.Append(flipped).Append('\n'); } } foreach (Hourglass g in glasses) sb.Append(g.Describe()).Append('\n'); Console.Write(sb); }}
C++main.cpp · 78 行
#include <algorithm>#include <iostream>#include <string>#include <utility>#include <vector>class Hourglass {public: explicit Hourglass(int capacity) : bottom_(capacity) {} void flip() { std::swap(top_, bottom_); } // seconds초가 흐른다. 이 동안 위 칸이 비게 되었으면 true를 돌려준다 bool run(int seconds) { int moved = std::min(seconds, top_); top_ -= moved; bottom_ += moved; return moved > 0 && top_ == 0; } // 값을 바꾸지 않는 메서드에는 const를 붙인다 bool isEmpty() const { return top_ == 0; } int remaining() const { return top_; } int bottom() const { return bottom_; }private: int top_ = 0; // 처음에는 모래가 전부 아래 칸에 있다 int bottom_;};int main() { std::ios::sync_with_stdio(false); int n, q; std::cin >> n >> q; std::vector<Hourglass> glasses; for (int i = 0; i < n; i++) { int c; std::cin >> c; glasses.emplace_back(c); } int elapsed = 0; for (int k = 0; k < q; k++) { std::string cmd; std::cin >> cmd; if (cmd == "flip") { int i; std::cin >> i; glasses[i - 1].flip(); } else if (cmd == "wait") { int t; std::cin >> t; elapsed += t; int done = 0; for (Hourglass& g : glasses) { // &가 없으면 복사본에 시간이 흐른다 if (g.run(t)) done++; } std::cout << done << '\n'; } else if (cmd == "until") { int i; std::cin >> i; // 흐를 시간은 반복 전에 한 번만 묻는다(반복 중에 물으면 i번이 비고 나서 0이 된다) int t = glasses[i - 1].remaining(); elapsed += t; for (Hourglass& g : glasses) g.run(t); std::cout << elapsed << '\n'; } else { int flipped = 0; for (Hourglass& g : glasses) { if (g.isEmpty()) { g.flip(); flipped++; } } std::cout << flipped << '\n'; } } for (const Hourglass& g : glasses) std::cout << g.remaining() << ' ' << g.bottom() << '\n';}