{ }codelper
removingiterating listsP0244

Card row clean-up commands

n number cards lie in a row on a table. Process q commands from top to bottom, taking cards out. Positions are counted from the leftmost card as 1. When a card is taken out, the cards to its right slide left, so no gap remains. del i takes out the i-th card.
If i is less than 1 or greater than the current number of cards, nothing happens. drop x takes out every card with the number x. every m takes out the cards at positions m, 2m, 3m, … of the row as it was just before this command. dedup keeps only the leftmost card of each number and takes out the other cards with the same number. print prints the numbers of the current row from the left, separated by single spaces, on one line.
If there are no cards, print -. The taking-out commands may be given when there are no cards; then nothing happens. The first line gives n, and the second line gives the n card numbers from the left. The third line gives q, and the next q lines give one command each. Print one line for each print.

Input
1 ≤ n ≤ 5,000, 1 ≤ q ≤ 300.
Card numbers and x are integers from -1,000 to 1,000.
The i of del is an integer from -10 to 10,000, and the m of every is an integer from 1 to 10,000.
There are 1 to 20 print commands
Output
As many lines as print commands
Example 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
Example 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
Input (stdin)

When you run, these lines are fed to input()/stdin in order (the program doesn't stop to ask).

$ Ready

Open this on a computer to write and run code. On mobile you can read the problem and the solutions.

In other languagesShow solutions by language · 8 languages

There are three ways to take things out: by position, by value, and by filtering into a new list.
By position: 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 RemoveAt(i - 1); in C, memmove shifts the rest left by one.
Removing every match by value: a Python list comprehension, JS/TS filter, Java removeIf, C# RemoveAll, C++ erase(remove(…), end()).
Trap ① deleting while walking forward: each deletion shifts the rest left, so doing every with a for loop that dels every m-th position goes wrong from the second deletion, and doing drop with splice skips an equal value right next to it.
Collect what you keep into a new list (Craykon also collects with kept.Add), or, as in C, keep separate read and write positions.
② Python negative indexes: del a[-1] is the last item, so checking only i <= len(a) makes del 0 remove the last card.
Also check that i is at least 1.
JS/TS splice(-1, 1) also removes the last item; Java, C# and Craykon raise an error out of range, and in C and C++ going out of range is undefined behaviour.
③ In Java, remove(x) on a List<Integer> with an int removes position x, not the value.
To remove by value use remove(Integer.valueOf(x)), and even that removes only one.
④ C# Remove(x), Craykon Remove(x) and Python a.remove(x) remove only the first match.
⑤ Positions in every start at 1.
Asking j % m == 0 with 0-based j removes the first card.
⑥ dedup keeps the leftmost one.
Python dict.fromkeys, JS new Set and Java LinkedHashSet keep first-seen order.
C# Distinct keeps it in practice too, but its documentation does not promise that order.

Pythonmain.py · 31 lines
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 lines
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 lines
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 lines
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 lines
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 lines
#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 lines
#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 lines
Console.ReadLine();a = Console.ReadNumbers();q = Console.ReadLine().ToNumber();for (t = 0; t < q; t++){    p = Console.ReadLine().Trim().Split(" ");    cmd = p[0];    switch (cmd)    {        case "del":            i = p[1].ToNumber();            if (i >= 1 && i <= a.Count)            {                a.RemoveAt(i - 1);            }            break;        case "drop":            x = p[1].ToNumber();            // 지우며 돌지 않고 남길 것만 새 목록에 모은다            kept = [];            foreach (v in a)            {                if (v != x)                {                    kept.Add(v);                }            }            a = kept;            break;        case "every":            m = p[1].ToNumber();            kept = [];            for (j = 0; j < a.Count; j++)            {                if ((j + 1) % m != 0)                {                    kept.Add(a[j]);                }            }            a = kept;            break;        case "dedup":            seen = Dict();            kept = [];            foreach (v in a)            {                if (!seen.Contains(v))                {                    seen[v] = true;                    kept.Add(v);                }            }            a = kept;            break;        default:            if (a.Count > 0)            {                Console.WriteLine(a.Join(" "));            }            else            {                Console.WriteLine("-");            }            break;    }}