{ }codelper
switch겹친 조건P0242

텔레비전 리모컨 키

채널이 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, ?
가운데 하나다.
?는 하나 이상 있다
출력
?
수만큼의 줄
예시 1 · stdin
50
?P?37?U?BB?M?+?D5#?P?9P?
stdout
OFF
CH 1 VOL 10
CH 37 VOL 10
CH 38 VOL 10
CH 38 VOL 10
CH 38 MUTE
CH 38 VOL 11
CH 5 VOL 11
OFF
CH 5 VOL 11
예시 2 · stdin
3
PD?UU?B?000#?40#?+M?M?
stdout
CH 3 VOL 10
CH 2 VOL 10
CH 1 VOL 10
CH 1 VOL 10
CH 1 VOL 10
CH 1 MUTE
CH 1 VOL 11
main.py
입력(stdin)

실행하면 이 줄들이 차례로 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, to  def 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);                    }                    그만;            }            그만;    }}