채널이 1번부터 c번까지 있는 텔레비전을 리모컨으로 다룬다.
처음에 텔레비전은 꺼져 있고, 채널은 1번, 소리는 10, 소리 끔은 풀려 있으며, 전 채널은 없고, 모아 둔 숫자도 없다.
키는 한 글자이고, 누른 차례대로 한 줄에 주어진다.
텔레비전이 꺼져 있으면 P와 ? 말고는 모든 키를 무시한다.
꺼져 있을 때 P는 텔레비전을 켜고, ?는 OFF를 한 줄에 출력한다.
켤 때 채널, 소리, 소리 끔, 전 채널은 끌 때 그대로다.
켜져 있을 때 숫자 키 0~9는 그 숫자를 모아 둔 숫자의 끝에 붙인다. 모아 둔 숫자가 세 자리가 되면 바로 '숫자 처리'를 한다.
켜져 있을 때 숫자가 아닌 키는 먼저 '숫자 처리'를 하고, 그다음 자기 일을 한다.
'숫자 처리'는 모아 둔 숫자가 있을 때만 하며, 모아 둔 숫자를 수로 읽고(007은 7) 비운다. 그 수가 1 이상 c 이하이면 그 채널로 간다. 범위 밖이면 아무 채널로도 가지 않는다.
켜져 있을 때 키마다 하는 일은 다음과 같다.
- #: 아무것도 하지 않는다(숫자 처리만 한다).
- P: 텔레비전을 끈다.
- U: 다음 채널로 간다. c번 다음은 1번이다.
- D: 앞 채널로 간다. 1번 앞은 c번이다.
- B: 전 채널로 간다. 전 채널이 없으면 아무것도 하지 않는다.
- +: 소리를 1 키운다(30보다 커지지 않는다). 소리 끔을 푼다.
- -: 소리를 1 줄인다(0보다 작아지지 않는다). 소리 끔을 푼다.
- M: 소리 끔을 켜거나 푼다(바꾼다).
- ?: 소리 끔이 켜져 있으면 CH 채널 MUTE, 아니면 CH 채널 VOL 소리를 한 줄에 출력한다.
어떤 채널로 '간다'는 것은, 그 채널이 지금 채널과 다를 때만 지금 채널을 전 채널로 기억하고 그 채널을 지금 채널로 바꾸는 것이다. 지금 채널과 같으면 아무것도 바뀌지 않는다.
키를 모두 누른 뒤 남은 숫자는 처리하지 않는다.
첫 줄에 c, 둘째 줄에 키들이 빈칸 없이 주어진다.
?마다 한 줄씩 출력하라.
입력
2 ≤ c ≤ 999. 키는 1 ~ 10,000개이고, 0~9, #, P, U, D, B, +, -, M, ? 가운데 하나다. ?는 하나 이상 있다
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
키 하나로 갈래를 고르는 switch예요. 문자 하나를 고르는 모양은 C·C++·Java·C#·JS·TS switch (k) { case 'U': … }(JS·TS는 문자열 "U"), Python 3.10+ match k: case "U":, 크레이콘 선택 (k) { 경우 "U": … 그만; }이에요. 숫자 열 개처럼 같은 일을 하는 경우 묶기는 C·C++·JS·TS·C#(빈 case만) case '0': case '1': …, Java 화살표 case '+', '-' ->, Python case "+" | "-":, 크레이콘 경우 "0", "1", …:예요. 함정 ① 이어 내려가기: C·C++·JS·TS와 Java의 옛 case: 문은 break가 없으면 다음 case까지 실행해요. U 뒤에 break를 빠뜨리면 D까지 해서 채널이 제자리로 돌아와요. C#은 이것을 컴파일 오류로 막고, Java 화살표 switch·Python match·크레이콘 선택은 이어 내려가지 않아요. 크레이콘의 그만은 선택만 빠져나가요. ② 1번에서 D: (ch - 2) % c + 1은 C·C++·Java·C#·JS·TS·크레이콘에서 %가 음수를 남겨 0번이 돼요. (ch - 2 + c) % c + 1이나 Java Math.floorMod를 써요(Python %는 늘 0 이상이에요). ③ 겹친 조건의 차례: '꺼져 있나'를 switch보다 먼저 물어야 꺼진 동안 소리나 채널이 바뀌지 않아요. ④ 숫자가 아닌 키는 모든 키가 먼저 모아 둔 숫자를 처리해요(#만이 아니에요). 그래서 5U는 5번 다음인 6번이에요. ⑤ 같은 채널로 가면 전 채널을 덮어쓰지 않아요. ⑥ +·-는 소리 끔을 풀어요.
Pythonmain.py · 60 줄
c = int(input())keys = input().strip()power = Falsech, vol, muted = 1, 10, Falseprev = 0 # 바로 전 채널(0이면 아직 없음)buf = "" # 누른 숫자를 모아 둔 것out = []def go(to): """채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다.""" global ch, prev if to != ch: prev, ch = ch, todef commit(): global buf if buf: v = int(buf) # "007"은 7 buf = "" if 1 <= v <= c: go(v)for k in keys: if not power: # 꺼져 있으면 P와 ? 말고는 듣지 않는다 if k == "P": power = True elif k == "?": out.append("OFF") continue if k.isdigit(): buf += k if len(buf) == 3: commit() continue commit() # 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 match k: case "#": pass case "P": power = False case "U": go(ch % c + 1) case "D": go((ch - 2) % c + 1) # Python의 %는 늘 0 이상이라 1번 → c번 case "B": if prev: go(prev) case "+" | "-": vol = min(30, vol + 1) if k == "+" else max(0, vol - 1) muted = False case "M": muted = not muted case "?": out.append(f"CH {ch} MUTE" if muted else f"CH {ch} VOL {vol}")print("\n".join(out))
JavaScriptmain.js · 62 줄
const [cLine, keysLine] = require("fs").readFileSync(0, "utf8").split("\n");const c = Number(cLine);const keys = keysLine.trim();let power = false;let ch = 1, vol = 10, muted = false;let prev = 0; // 바로 전 채널(0이면 아직 없음)let buf = ""; // 누른 숫자를 모아 둔 것const out = [];const go = (to) => { if (to !== ch) [prev, ch] = [ch, to]; // 지금과 같으면 바꾼 것이 아니다};const commit = () => { if (buf === "") return; const v = Number(buf); // "007"은 7 buf = ""; if (v >= 1 && v <= c) go(v);};for (const k of keys) { if (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 if (k === "P") power = true; else if (k === "?") out.push("OFF"); continue; } if (k >= "0" && k <= "9") { buf += k; if (buf.length === 3) commit(); continue; } commit(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 switch (k) { case "#": break; case "P": power = false; break; case "U": go((ch % c) + 1); break; case "D": go(((ch - 2 + c) % c) + 1); // JS의 %는 음수를 남기니 c를 더해 둔다 break; case "B": if (prev !== 0) go(prev); break; case "+": case "-": // 두 경우가 같은 일을 하도록 일부러 이어 내려간다 vol = k === "+" ? Math.min(30, vol + 1) : Math.max(0, vol - 1); muted = false; break; case "M": muted = !muted; break; case "?": out.push(muted ? `CH ${ch} MUTE` : `CH ${ch} VOL ${vol}`); break; }}console.log(out.join("\n"));
TypeScriptmain.ts · 64 줄
import { readFileSync } from "node:fs";const [cLine, keysLine]: string[] = readFileSync(0, "utf8").split("\n");const c = Number(cLine);const keys = keysLine.trim();let power = false;let ch = 1, vol = 10, muted = false;let prev = 0; // 바로 전 채널(0이면 아직 없음)let buf = ""; // 누른 숫자를 모아 둔 것const out: string[] = [];const go = (to: number): void => { if (to !== ch) [prev, ch] = [ch, to]; // 지금과 같으면 바꾼 것이 아니다};const commit = (): void => { if (buf === "") return; const v = Number(buf); // "007"은 7 buf = ""; if (v >= 1 && v <= c) go(v);};for (const k of keys) { if (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 if (k === "P") power = true; else if (k === "?") out.push("OFF"); continue; } if (k >= "0" && k <= "9") { buf += k; if (buf.length === 3) commit(); continue; } commit(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 switch (k) { case "#": break; case "P": power = false; break; case "U": go((ch % c) + 1); break; case "D": go(((ch - 2 + c) % c) + 1); // JS의 %는 음수를 남기니 c를 더해 둔다 break; case "B": if (prev !== 0) go(prev); break; case "+": case "-": // 두 경우가 같은 일을 하도록 일부러 이어 내려간다 vol = k === "+" ? Math.min(30, vol + 1) : Math.max(0, vol - 1); muted = false; break; case "M": muted = !muted; break; case "?": out.push(muted ? `CH ${ch} MUTE` : `CH ${ch} VOL ${vol}`); break; }}console.log(out.join("\n"));
JavaMain.java · 62 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.IOException;public class Main { static int c, ch = 1, vol = 10, prev = 0; static boolean muted = false; static StringBuilder buf = new StringBuilder(); // 누른 숫자를 모아 둔 것 // 채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다 static void go(int to) { if (to != ch) { prev = ch; ch = to; } } static void commit() { if (buf.length() == 0) return; int v = Integer.parseInt(buf.toString()); // "007"은 7 buf.setLength(0); if (v >= 1 && v <= c) go(v); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); c = Integer.parseInt(in.readLine().trim()); String keys = in.readLine().trim(); boolean power = false; StringBuilder out = new StringBuilder(); for (char k : keys.toCharArray()) { if (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 if (k == 'P') power = true; else if (k == '?') out.append("OFF\n"); continue; } if (Character.isDigit(k)) { buf.append(k); if (buf.length() == 3) commit(); continue; } commit(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 // 화살표 switch는 이어 내려가지 않아 break가 필요 없다 switch (k) { case '#' -> { } case 'P' -> power = false; case 'U' -> go(ch % c + 1); case 'D' -> go(Math.floorMod(ch - 2, c) + 1); // floorMod는 늘 0 이상 case 'B' -> { if (prev != 0) go(prev); } case '+', '-' -> { vol = k == '+' ? Math.min(30, vol + 1) : Math.max(0, vol - 1); muted = false; } case 'M' -> muted = !muted; case '?' -> out.append("CH ").append(ch).append(muted ? " MUTE" : " VOL " + vol).append('\n'); default -> { } } } System.out.print(out); }}
C#Main.cs · 82 줄
using System;using System.Text;class Program{ static int c, ch = 1, vol = 10, prev = 0; static bool muted = false; static string buf = ""; // 누른 숫자를 모아 둔 것 // 채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다 static void Go(int to) { if (to != ch) { prev = ch; ch = to; } } static void Commit() { if (buf == "") return; int v = int.Parse(buf); // "007"은 7 buf = ""; if (v >= 1 && v <= c) Go(v); } static void Main() { c = int.Parse(Console.ReadLine().Trim()); string keys = Console.ReadLine().Trim(); bool power = false; var sb = new StringBuilder(); foreach (char k in keys) { if (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 if (k == 'P') power = true; else if (k == '?') sb.Append("OFF\n"); continue; } if (char.IsDigit(k)) { buf += k; if (buf.Length == 3) Commit(); continue; } Commit(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 // C#은 case 끝에 break가 없으면 컴파일 오류라서 이어 내려가는 실수가 없다 switch (k) { case '#': break; case 'P': power = false; break; case 'U': Go(ch % c + 1); break; case 'D': Go((ch - 2 + c) % c + 1); // C#의 %는 음수를 남기니 c를 더해 둔다 break; case 'B': if (prev != 0) Go(prev); break; case '+': case '-': // 빈 case는 다음 case와 묶을 수 있다 vol = k == '+' ? Math.Min(30, vol + 1) : Math.Max(0, vol - 1); muted = false; break; case 'M': muted = !muted; break; case '?': sb.Append(muted ? $"CH {ch} MUTE\n" : $"CH {ch} VOL {vol}\n"); break; } } Console.Write(sb); }}
C++main.cpp · 73 줄
#include <algorithm>#include <iostream>#include <string>int c, ch = 1, vol = 10, prev = 0;bool muted = false;std::string buf; // 누른 숫자를 모아 둔 것// 채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다void go(int to) { if (to != ch) { prev = ch; ch = to; }}void commit() { if (buf.empty()) return; int v = std::stoi(buf); // "007"은 7 buf.clear(); if (v >= 1 && v <= c) go(v);}int main() { std::string keys, out; std::cin >> c >> keys; bool power = false; for (char k : keys) { if (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 if (k == 'P') power = true; else if (k == '?') out += "OFF\n"; continue; } if (k >= '0' && k <= '9') { buf += k; if (buf.size() == 3) commit(); continue; } commit(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 switch (k) { case '#': break; case 'P': power = false; break; case 'U': go(ch % c + 1); break; case 'D': go((ch - 2 + c) % c + 1); // C++의 %는 음수를 남기니 c를 더해 둔다 break; case 'B': if (prev) go(prev); break; case '+': vol = std::min(30, vol + 1); muted = false; break; case '-': vol = std::max(0, vol - 1); muted = false; break; case 'M': muted = !muted; break; case '?': out += "CH " + std::to_string(ch) + (muted ? " MUTE" : " VOL " + std::to_string(vol)) + "\n"; break; } } std::cout << out;}
Cmain.c · 81 줄
#include <stdio.h>#include <stdlib.h>static int c, ch = 1, vol = 10, muted = 0, prev = 0;static char buf[4];static int blen = 0;/* 채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다 */static void go(int to) { if (to != ch) { prev = ch; ch = to; }}static void commit(void) { if (blen == 0) return; buf[blen] = '\0'; int v = atoi(buf); /* "007"은 7 */ blen = 0; if (v >= 1 && v <= c) go(v);}static char keys[10002];int main(void) { int power = 0; scanf("%d %10001s", &c, keys); for (char *p = keys; *p; p++) { char k = *p; if (!power) { /* 꺼져 있으면 P와 ? 말고는 듣지 않는다 */ if (k == 'P') power = 1; else if (k == '?') puts("OFF"); continue; } switch (k) { /* 숫자 열 개는 case를 잇대어 써서 한 곳으로 모은다(일부러 이어 내려감) */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': buf[blen++] = k; if (blen == 3) commit(); continue; /* 아래의 commit을 건너뛰고 다음 키로 */ default: break; } commit(); /* 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 */ switch (k) { case '#': break; case 'P': power = 0; break; case 'U': go(ch % c + 1); break; case 'D': go((ch - 2 + c) % c + 1); /* C의 %는 음수를 남기니 c를 더해 둔다 */ break; case 'B': if (prev) go(prev); break; case '+': vol = vol < 30 ? vol + 1 : 30; muted = 0; break; case '-': vol = vol > 0 ? vol - 1 : 0; muted = 0; break; case 'M': muted = !muted; break; case '?': if (muted) printf("CH %d MUTE\n", ch); else printf("CH %d VOL %d\n", ch, vol); break; } } return 0;}
Craykonmain.cray · 111 줄
c = 콘솔.줄읽기().수로변환();keys = 콘솔.줄읽기().공백제거();power = 거짓;ch = 1;vol = 10;muted = 거짓;prev = 0; // 바로 전 채널(0이면 아직 없음)buf = ""; // 누른 숫자를 모아 둔 것// 채널을 to로 바꾼다. 지금과 같으면 바꾼 것이 아니다가기(to){ 만약 (to != ch) { prev = ch; ch = to; }}모은숫자처리(){ 만약 (buf != "") { v = buf.수로변환(); // "007"은 7 buf = ""; 만약 (v >= 1 && v <= c) { 가기(v); } }}반복 (i = 0; i < keys.길이; i++){ k = keys[i]; 만약 (!power) { // 꺼져 있으면 P와 ? 말고는 듣지 않는다 만약 (k == "P") { power = 참; } 아니면 만약 (k == "?") { 콘솔.쓰기("OFF"); } 건너뛰기; } 선택 (k) { 경우 "0": 경우 "1": 경우 "2": 경우 "3": 경우 "4": 경우 "5": 경우 "6": 경우 "7": 경우 "8": 경우 "9": buf = buf + k; 만약 (buf.길이 == 3) { 모은숫자처리(); } 그만; 그밖에: 모은숫자처리(); // 숫자가 아닌 키는 모아 둔 숫자부터 처리한다 선택 (k) { 경우 "P": power = 거짓; 그만; 경우 "U": 가기(ch % c + 1); 그만; 경우 "D": 가기((ch - 2 + c) % c + 1); // %는 음수를 남기니 c를 더해 둔다 그만; 경우 "B": 만약 (prev != 0) { 가기(prev); } 그만; 경우 "+": vol = 수학.작은수(30, vol + 1); muted = 거짓; 그만; 경우 "-": vol = 수학.큰수(0, vol - 1); muted = 거짓; 그만; 경우 "M": muted = !muted; 그만; 경우 "?": 만약 (muted) { 콘솔.쓰기("CH " + ch + " MUTE"); } 아니면 { 콘솔.쓰기("CH " + ch + " VOL " + vol); } 그만; } 그만; }}