{ }codelper
목록에서 빼기목록 돌기P0244

카드 줄 정리 명령

탁자 위에 수 카드 n장이 한 줄로 놓여 있다. 명령 q개를 위에서부터 차례로 처리하며 카드를 빼낸다. 카드의 자리는 맨 왼쪽을 1로 하여 센다. 카드를 빼면 그 오른쪽 카드들이 왼쪽으로 당겨져 빈자리가 없어진다. del i는 i번째 카드 한 장을 뺀다.
i가 1보다 작거나 지금 카드 수보다 크면 아무 일도 하지 않는다. drop x는 수가 x인 카드를 모두 뺀다. every m은 이 명령을 하기 직전의 줄에서 m번째, 2m번째, 3m번째, … 자리의 카드를 모두 뺀다. dedup은 같은 수의 카드가 여러 장이면 가장 왼쪽 한 장만 남기고 나머지를 뺀다. print는 지금 줄의 카드 수를 왼쪽부터 빈칸 하나씩으로 나눠 한 줄에 출력한다.
카드가 없으면 -를 출력한다. 빼는 명령은 카드가 없을 때도 할 수 있고, 그때는 아무 일도 일어나지 않는다. 첫 줄에 n, 둘째 줄에 카드의 수 n개가 왼쪽부터 주어진다. 셋째 줄에 q, 다음 q줄에 명령이 하나씩 주어진다. print마다 한 줄씩 출력하라.

입력
1 ≤ n ≤ 5,000, 1 ≤ q ≤ 300.
카드의 수와 x는 -1,000 이상 1,000 이하의 정수.
del의 i는 -10 이상 10,000 이하의 정수, every의 m은 1 이상 10,000 이하의 정수.
print는 1개 이상 20개 이하
출력
print 수만큼의 줄
예시 1 · stdin
7
5 3 5 5 8 3 9
6
del 2
print
drop 5
print
every 2
print
stdout
5 5 5 8 3 9
8 3 9
8 9
예시 2 · stdin
10
4 4 1 4 2 1 7 4 2 1
8
dedup
print
every 3
print
del 0
del 3
del 4
print
stdout
4 1 2 7
4 1 7
4 1
main.py
입력(stdin)

실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).

$ 준비됐어요

코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.

다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이

빼는 방법이 셋이에요: 자리로 빼기, 값으로 빼기, 조건으로 걸러 새로 모으기.
자리로 빼기는 Python del a[i - 1]·a.pop(i - 1), JS·TS a.splice(i - 1, 1), Java list.remove(i - 1), C# RemoveAt(i - 1), C++ a.erase(a.begin() + (i - 1)), 크레이콘 자리빼기(i - 1)이고, C는 memmove로 뒤를 한 칸 당겨요.
값으로 모두 빼기는 Python 리스트 내포, JS·TS filter, Java removeIf, C# RemoveAll, C++ erase(remove(…), end())예요.
함정 ① 앞에서부터 돌며 지우기: 하나를 지우면 뒤가 당겨져서, every를 for 문으로 m번째마다 del하면 두 번째부터 자리가 밀리고, drop을 splice로 하면 바로 붙은 같은 값을 건너뛰어요.
남길 것만 새 목록에 모으거나(크레이콘도 kept.넣기로 모아요) C처럼 읽는 자리와 쓰는 자리를 따로 두면 안전해요.
② Python의 음수 자리: del a[-1]은 맨 끝 칸이라 i <= len(a)만 물으면 del 0이 맨 끝 카드를 지워요.
1 이상인지도 물어야 해요.
JS·TS splice(-1, 1)도 맨 끝을 빼고, Java·C#·크레이콘은 범위 밖이면 오류가 나며, C·C++은 범위를 넘으면 정의되지 않은 동작이에요.
③ Java List<Integer>의 remove(x)에 int를 주면 값이 아니라 x번 자리를 빼요.
값으로 빼려면 remove(Integer.valueOf(x))이고 그것도 하나만 빼요.
④ C# Remove(x), 크레이콘 빼기(x), Python a.remove(x)는 처음 하나만 빼요.
⑤ every의 자리는 1부터 세요.
0부터 센 번호로 j % m == 0을 물으면 맨 앞 카드가 빠져요.
⑥ dedup은 가장 왼쪽 것을 남겨요.
Python dict.fromkeys, JS new Set, Java LinkedHashSet은 처음 나온 차례를 지켜요.
C# Distinct도 실제로는 차례를 지키지만 문서는 그 차례를 약속하지 않아요.

Pythonmain.py · 31 줄
import sys lines = sys.stdin.read().split("\n")a = list(map(int, lines[1].split()))q = int(lines[2])out = []for line in lines[3:3 + q]:    cmd, *arg = line.split()    if cmd == "del":        i = int(arg[0])        # 범위를 먼저 묻는다: a[-1]은 맨 끝 칸이라 i = 0이면 엉뚱한 칸이 빠진다        if 1 <= i <= len(a):            del a[i - 1]    elif cmd == "drop":        x = int(arg[0])        a = [v for v in a if v != x]  # 지우며 돌지 않고 남길 것만 새로 모은다    elif cmd == "every":        m = int(arg[0])        # 자리는 이 명령 전의 목록에서 센다        a = [v for pos, v in enumerate(a, start=1) if pos % m != 0]    elif cmd == "dedup":        seen = set()        kept = []        for v in a:            if v not in seen:                seen.add(v)                kept.append(v)        a = kept    else:        out.append(" ".join(map(str, a)) if a else "-")print("\n".join(out))
JavaScriptmain.js · 20 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");let a = lines[1].trim().split(/\s+/).map(Number);const q = Number(lines[2]);const out = [];for (const line of lines.slice(3, 3 + q)) {  const [cmd, arg] = line.trim().split(" ");  const v = Number(arg);  if (cmd === "del") {    if (v >= 1 && v <= a.length) a.splice(v - 1, 1);  } else if (cmd === "drop") {    a = a.filter((x) => x !== v); // 지우며 돌지 않고 남길 것만 새로 모은다  } else if (cmd === "every") {    a = a.filter((_, i) => (i + 1) % v !== 0); // 자리는 이 명령 전의 목록에서 1부터 센다  } else if (cmd === "dedup") {    a = [...new Set(a)]; // Set은 처음 넣은 차례를 지킨다  } else {    out.push(a.length > 0 ? a.join(" ") : "-");  }}console.log(out.join("\n"));
TypeScriptmain.ts · 22 줄
import { readFileSync } from "node:fs"; const lines: string[] = readFileSync(0, "utf8").split("\n");let a: number[] = lines[1].trim().split(/\s+/).map(Number);const q = Number(lines[2]);const out: string[] = [];for (const line of lines.slice(3, 3 + q)) {  const [cmd, arg] = line.trim().split(" ");  const v = Number(arg);  if (cmd === "del") {    if (v >= 1 && v <= a.length) a.splice(v - 1, 1);  } else if (cmd === "drop") {    a = a.filter((x) => x !== v); // 지우며 돌지 않고 남길 것만 새로 모은다  } else if (cmd === "every") {    a = a.filter((_, i) => (i + 1) % v !== 0); // 자리는 이 명령 전의 목록에서 1부터 센다  } else if (cmd === "dedup") {    a = [...new Set(a)]; // Set은 처음 넣은 차례를 지킨다  } else {    out.push(a.length > 0 ? a.join(" ") : "-");  }}console.log(out.join("\n"));
JavaMain.java · 49 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.io.IOException;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        in.readLine();        List<Integer> a = new ArrayList<>();        for (String s : in.readLine().trim().split("\\s+")) a.add(Integer.parseInt(s));        int q = Integer.parseInt(in.readLine().trim());        StringBuilder out = new StringBuilder();        for (int t = 0; t < q; t++) {            String[] p = in.readLine().trim().split(" ");            switch (p[0]) {                case "del" -> {                    int i = Integer.parseInt(p[1]);                    // int를 주면 remove(int index): 자리로 뺀다                    if (i >= 1 && i <= a.size()) a.remove(i - 1);                }                case "drop" -> {                    int x = Integer.parseInt(p[1]);                    a.removeIf(v -> v == x); // Integer와 int를 ==로 견주면 v가 int로 풀려 값으로 비교된다                }                case "every" -> {                    int m = Integer.parseInt(p[1]);                    List<Integer> kept = new ArrayList<>();                    for (int i = 0; i < a.size(); i++)                        if ((i + 1) % m != 0) kept.add(a.get(i));                    a = kept;                }                case "dedup" -> {                    Set<Integer> seen = new HashSet<>();                    a.removeIf(v -> !seen.add(v)); // add가 false면 이미 본 값                }                default -> {                    if (a.isEmpty()) out.append("-");                    for (int i = 0; i < a.size(); i++) out.append(i > 0 ? " " : "").append(a.get(i));                    out.append('\n');                }            }        }        System.out.print(out);    }}
C#Main.cs · 41 줄
using System;using System.Collections.Generic;using System.Linq;using System.Text; class Program{    static void Main()    {        Console.ReadLine();        var a = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToList();        int q = int.Parse(Console.ReadLine().Trim());        var sb = new StringBuilder();        for (int t = 0; t < q; t++)        {            string[] p = Console.ReadLine().Trim().Split(' ');            switch (p[0])            {                case "del":                    int i = int.Parse(p[1]);                    if (i >= 1 && i <= a.Count) a.RemoveAt(i - 1);                    break;                case "drop":                    int x = int.Parse(p[1]);                    a.RemoveAll(v => v == x); // Remove(x)는 처음 하나만 뺀다                    break;                case "every":                    int m = int.Parse(p[1]);                    a = a.Where((v, idx) => (idx + 1) % m != 0).ToList();                    break;                case "dedup":                    a = a.Distinct().ToList(); // Distinct는 처음 나온 차례를 지킨다                    break;                default:                    sb.Append(a.Count > 0 ? string.Join(" ", a) : "-").Append('\n');                    break;            }        }        Console.Write(sb);    }}
C++main.cpp · 44 줄
#include <algorithm>#include <iostream>#include <string>#include <unordered_set>#include <vector> int main() {    std::ios::sync_with_stdio(false);    int n, q;    std::cin >> n;    std::vector<int> a(n);    for (int &v : a) std::cin >> v;    std::cin >> q;    std::string out;    for (int t = 0; t < q; t++) {        std::string cmd;        std::cin >> cmd;        if (cmd == "del") {            int i;            std::cin >> i;            if (i >= 1 && i <= (int)a.size()) a.erase(a.begin() + (i - 1));        } else if (cmd == "drop") {            int x;            std::cin >> x;            // remove는 남길 것을 앞으로 모으기만 하고, erase가 실제로 줄인다            a.erase(std::remove(a.begin(), a.end(), x), a.end());        } else if (cmd == "every") {            int m;            std::cin >> m;            std::vector<int> kept;            for (size_t i = 0; i < a.size(); i++)                if ((i + 1) % m != 0) kept.push_back(a[i]);            a = kept;        } else if (cmd == "dedup") {            std::unordered_set<int> seen;            a.erase(std::remove_if(a.begin(), a.end(), [&](int v) { return !seen.insert(v).second; }), a.end());        } else {            if (a.empty()) out += "-";            for (size_t i = 0; i < a.size(); i++) out += (i ? " " : "") + std::to_string(a[i]);            out += '\n';        }    }    std::cout << out;}
Cmain.c · 47 줄
#include <stdio.h>#include <string.h> static int a[5000];static int len;static char seen[2001]; /* 값 -1000..1000 → 칸 0..2000 */ int main(void) {    int q;    scanf("%d", &len);    for (int i = 0; i < len; i++) scanf("%d", &a[i]);    scanf("%d", &q);    for (int t = 0; t < q; t++) {        char cmd[8];        int v = 0, w = 0;        scanf("%7s", cmd);        if (strcmp(cmd, "print") != 0 && strcmp(cmd, "dedup") != 0) scanf("%d", &v);        if (strcmp(cmd, "del") == 0) {            if (v >= 1 && v <= len) {                memmove(&a[v - 1], &a[v], sizeof a[0] * (len - v)); /* 뒤를 한 칸 당긴다 */                len--;            }        } else if (strcmp(cmd, "drop") == 0) {            /* 남길 것을 앞으로 모은다(읽는 자리 r, 쓰는 자리 w) */            for (int r = 0; r < len; r++)                if (a[r] != v) a[w++] = a[r];            len = w;        } else if (strcmp(cmd, "every") == 0) {            for (int r = 0; r < len; r++)                if ((r + 1) % v != 0) a[w++] = a[r];            len = w;        } else if (strcmp(cmd, "dedup") == 0) {            memset(seen, 0, sizeof seen);            for (int r = 0; r < len; r++)                if (!seen[a[r] + 1000]) {                    seen[a[r] + 1000] = 1;                    a[w++] = a[r];                }            len = w;        } else {            if (len == 0) printf("-");            for (int i = 0; i < len; i++) printf(i ? " %d" : "%d", a[i]);            printf("\n");        }    }    return 0;}
Craykonmain.cray · 66 줄
콘솔.줄읽기();a = 콘솔.수들읽기();q = 콘솔.줄읽기().수로변환();반복 (t = 0; t < q; t++){    p = 콘솔.줄읽기().공백제거().나누기(" ");    cmd = p[0];    선택 (cmd)    {        경우 "del":            i = p[1].수로변환();            만약 (i >= 1 && i <= a.개수)            {                a.자리빼기(i - 1);            }            그만;        경우 "drop":            x = p[1].수로변환();            // 지우며 돌지 않고 남길 것만 새 목록에 모은다            kept = [];            각각 (v 에서 a)            {                만약 (v != x)                {                    kept.넣기(v);                }            }            a = kept;            그만;        경우 "every":            m = p[1].수로변환();            kept = [];            반복 (j = 0; j < a.개수; j++)            {                만약 ((j + 1) % m != 0)                {                    kept.넣기(a[j]);                }            }            a = kept;            그만;        경우 "dedup":            seen = 사전();            kept = [];            각각 (v 에서 a)            {                만약 (!seen.있나(v))                {                    seen[v] = 참;                    kept.넣기(v);                }            }            a = kept;            그만;        그밖에:            만약 (a.개수 > 0)            {                콘솔.쓰기(a.잇기(" "));            }            아니면            {                콘솔.쓰기("-");            }            그만;    }}