机の上に数字カード 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
エラー一覧00F8 ↓ · ⇧F8 ↑
入力(stdin)
実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。
$ 準備完了
コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。
ほかの言語では?言語別の解答を見る · 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))、Craykon 位置で取り除く(i - 1) で、C は memmove で後ろを一つ詰めます。 値で全部抜くのは Python のリスト内包表記、JS・TS filter、Java removeIf、C# RemoveAll、C++ erase(remove(…), end()) です。 落とし穴 ① 前から回りながら消す:一つ消すと後ろが詰まるので、every を for 文で m 番目ごとに del すると二つ目から位置がずれ、drop を splice でやるとすぐ隣の同じ値を飛ばします。 残すものだけ新しいリストに集めるか(Craykon も kept.追加 で集めます)、C のように読む位置と書く位置を分けると安全です。 ② Python の負の添字:del a[-1] は末尾なので、i <= len(a) だけ確かめると del 0 が末尾のカードを消します。 1 以上かも確かめます。 JS・TS splice(-1, 1) も末尾を抜き、Java・C#・Craykon は範囲外だとエラーになり、C・C++ は範囲を超えると未定義動作です。 ③ Java List<Integer> の remove(x) に int を渡すと、値ではなく x 番目の位置を抜きます。 値で抜くなら remove(Integer.valueOf(x)) で、それも一つだけです。 ④ C# Remove(x)、Craykon 取り除く(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 syslines = 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.つなぐ(" ")); } でなければ { コンソール.書く("-"); } 抜ける; }}