모래시계 n개가 있고, i번 모래시계에는 모래가 c_i알 들어 있다.
처음에는 모든 모래시계의 모래가 전부 아래 칸에 있다.
시간이 흐르면 위 칸에 모래가 있는 모래시계마다 1초에 한 알씩 위 칸에서 아래 칸으로 떨어지고, 위 칸이 비면 그 모래시계는 더 흐르지 않는다.
모래시계를 클래스로 만들고, '뒤집기', 't초 흐르기', '위 칸이 비었는지 묻기', '위 칸에 남은 모래 수 묻기'를 메서드로 만들어 다음 명령 q개를 차례로 처리하라.
flip i: i번 모래시계를 뒤집는다(위 칸과 아래 칸의 모래 수가 서로 바뀐다). 아무것도 출력하지 않는다.
wait t: 모든 모래시계에 t초가 흐른다. 이 t초 사이에 위 칸이 비게 된 모래시계의 수를 출력한다. 명령 전부터 위 칸이 비어 있던 모래시계는 세지 않는다.
until i: 명령 직전에 i번 모래시계의 위 칸에 남아 있던 모래 수만큼의 초가 모든 모래시계에 똑같이 흐른다(i번의 위 칸이 이미 비어 있으면 시간은 흐르지 않는다). 그런 다음 맨 처음부터 지금까지 wait와 until로 흐른 시간을 모두 더한 초를 출력한다.
flipdone: 위 칸이 비어 있는 모래시계를 모두 뒤집고, 뒤집은 모래시계의 수를 출력한다.
명령을 모두 처리한 뒤 1번부터 n번까지 모래시계마다 위 칸의 모래 수와 아래 칸의 모래 수를 빈칸 하나로 띄워 한 줄씩 출력한다.
입력
첫 줄에 모래시계 수 n과 명령 수 q가 빈칸 하나로 띄워 주어진다. 둘째 줄에 c_1, …, c_n이 빈칸 하나씩 띄워 주어진다. 다음 q줄에 명령이 한 줄에 하나씩 주어진다. 1 ≤ n ≤ 100, 1 ≤ q ≤ 1,000, 1 ≤ c_i ≤ 1,000,000, 1 ≤ t ≤ 1,000,000, 1 ≤ i ≤ n
출력
wait, until, flipdone 명령마다 답을 한 줄에 하나씩 출력한다(쉼표 없이 숫자만). 그 뒤 n줄에 모래시계마다 위 칸과 아래 칸의 모래 수를 빈칸 하나로 띄워 출력한다
예시 1 · stdin
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()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 6개 언어 풀이
이 문제는 클래스가 있는 Python·JavaScript·TypeScript·Java·C#·C++만 받아요(C에는 클래스가 없고, 크레이콘은 아직 클래스를 만들 수 없어요). 메서드는 객체 안의 값을 읽거나 바꾸는 함수예요. 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_)으로 한 줄에 쓰고, 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';}