정수 목록을 규칙 s개로 차례차례 다듬는다.
첫 줄에 n이, 둘째 줄에 정수 n개가 빈칸으로 띄워 주어진다.
셋째 줄에 s가, 다음 s줄에 규칙이 한 줄에 하나씩 "이름 k" 꼴로 주어진다.
규칙은 여섯 가지이고, 앞의 셋은 목록의 모든 수를 바꾸고 뒤의 셋은 조건에 맞는 수만 남긴다.
add k: 모든 수 x를 x + k로 바꾼다.
mul k: 모든 수 x를 x × k로 바꾼다.
mod k: 모든 수 x를, x를 k로 나눈 나머지 r로 바꾼다. 여기서 r은 0 이상 k 미만이고 x - r은 k의 배수다. 그래서 -7을 3으로 나눈 나머지는 2다.
gt k: k보다 큰 수만 남긴다.
lt k: k보다 작은 수만 남긴다.
div k: k의 배수만 남긴다. 0과 음수도 k의 배수일 수 있다.
남는 수들의 차례는 그대로다.
규칙을 하나 쓸 때마다, 그 규칙까지 쓴 목록을 한 줄에 빈칸 하나씩 띄워 출력하라.
목록이 비면 -를 출력하고, 빈 목록에 다음 규칙을 써도 빈 목록이다.
풀이에는 "목록, 규칙 함수, k"를 받아 새 목록을 돌려주는 함수 두 개를 만들어라. 하나는 모든 수를 바꾸는 함수이고, 하나는 조건에 맞는 수만 남기는 함수다.
규칙마다 그 규칙의 함수를 값으로 넘겨 이 두 함수를 부른다.
입력
1 ≤ n ≤ 300, 1 ≤ s ≤ 20, 처음 수는 -1,000,000 이상 1,000,000 이하. add는 -1,000,000 ≤ k ≤ 1,000,000, mul은 -10 ≤ k ≤ 10, mod는 1 ≤ k ≤ 1,000, gt·lt는 -1,000,000,000 ≤ k ≤ 1,000,000,000, div는 1 ≤ k ≤ 100. 어느 단계에서나 목록의 모든 수의 절댓값은 1,000,000,000 이하다
출력
규칙마다 한 줄: 그때의 목록, 비었으면 -
예시 1 · stdin
5
3 -7 10 0 5
4
mul 2
mod 4
gt 0
add -1
stdout
6 -14 20 0 10
2 2 0 0 2
2 2 2
1 1 1
예시 2 · stdin
4
2 4 6 1
2
div 2
lt 0
stdout
2 4 6
-
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
함수를 값으로 넘기는 방법이 언어마다 달라요. Python은 def로 만든 함수 이름이나 lambda x, k: x + k를 그대로 넘기고, JS·TS는 화살표 함수 (x, k) => x + k를 넘겨요(TS는 (x: number, k: number) => number 같은 함수 타입을 붙여요). Java는 람다를 받을 함수형 인터페이스가 있어야 해서 IntBinaryOperator, BiPredicate<Integer, Integer>를 쓰고, C#은 Func<int, int, int>, Func<int, int, bool>을 써요. C는 함수 포인터 int (*rule)(int, int)로 넘기고, C++는 std::function<int(int, int)>에 람다를 담아요. 크레이콘에는 람다가 없어서 더하기(x, k)처럼 이름을 붙여 만든 함수를 이름으로 넘기고, 사전()에 이름 → 함수를 담아 골라요. 첫째 함정은 음수의 나머지예요. JS·TS·Java·C#·C·C++·크레이콘의 %는 나누어지는 수의 부호를 따라서 -7 % 3이 -1이에요. Python의 %만 2를 줘요. (x % k + k) % k로 고치거나 Java Math.floorMod(x, k)를 써요. 둘째 함정은 걸러 내는 방법이에요. Python에서 for x in a: 안에서 a.remove(x)를 하면 뒤의 칸이 당겨져 와서 바로 다음 수를 건너뛰니, 남길 수를 새 목록에 담아요. JS·TS의 map·filter와 이 문제의 두 함수는 새 목록을 돌려주니, 돌려받은 목록을 다시 담지 않으면 아무것도 바뀌지 않아요. gt·lt는 k와 같은 수를 남기지 않으니 >=·<=가 아니라 >·<예요.
Pythonmain.py · 41 줄
# 모든 수를 바꾸는 규칙(x, k → 새 수)def add(x, k): return x + kdef mul(x, k): return x * kdef mod(x, k): return x % k # Python의 %는 k가 양수면 늘 0 이상 k 미만# 남길지 정하는 규칙(x, k → 참·거짓)def gt(x, k): return x > kdef lt(x, k): return x < kdef div(x, k): return x % k == 0# 함수를 값으로 받는 함수 두 개def change_all(a, rule, k): return [rule(x, k) for x in a]def keep_only(a, rule, k): return [x for x in a if rule(x, k)]CHANGE = {"add": add, "mul": mul, "mod": mod}KEEP = {"gt": gt, "lt": lt, "div": div}n = int(input())a = list(map(int, input().split()))s = int(input())for _ in range(s): name, k = input().split() k = int(k) if name in CHANGE: a = change_all(a, CHANGE[name], k) else: a = keep_only(a, KEEP[name], k) print(" ".join(map(str, a)) if a else "-")
JavaScriptmain.js · 28 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");// 모든 수를 바꾸는 규칙(x, k → 새 수). JS의 %는 음수에서 음수가 나오니 k를 더해 한 번 더 나눈다const CHANGE = { add: (x, k) => x + k, mul: (x, k) => x * k, mod: (x, k) => ((x % k) + k) % k,};// 남길지 정하는 규칙(x, k → 참·거짓)const KEEP = { gt: (x, k) => x > k, lt: (x, k) => x < k, div: (x, k) => x % k === 0,};// 함수를 값으로 받는 함수 두 개. map·filter는 새 배열을 돌려준다const changeAll = (a, rule, k) => a.map((x) => rule(x, k));const keepOnly = (a, rule, k) => a.filter((x) => rule(x, k));let a = lines[1].trim().split(/\s+/).map(Number);const s = Number(lines[2]);const out = [];for (let i = 0; i < s; i++) { const [name, ks] = lines[3 + i].trim().split(/\s+/); const k = Number(ks); a = name in CHANGE ? changeAll(a, CHANGE[name], k) : keepOnly(a, KEEP[name], k); // -0 % 3은 -0이지만 join은 "0"으로 쓴다 out.push(a.length ? a.join(" ") : "-");}console.log(out.join("\n"));
TypeScriptmain.ts · 30 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");type Change = (x: number, k: number) => number;type Keep = (x: number, k: number) => boolean;// 모든 수를 바꾸는 규칙. JS·TS의 %는 음수에서 음수가 나오니 k를 더해 한 번 더 나눈다const CHANGE: Record<string, Change> = { add: (x, k) => x + k, mul: (x, k) => x * k, mod: (x, k) => ((x % k) + k) % k,};// 남길지 정하는 규칙const KEEP: Record<string, Keep> = { gt: (x, k) => x > k, lt: (x, k) => x < k, div: (x, k) => x % k === 0,};// 함수를 값으로 받는 함수 두 개const changeAll = (a: number[], rule: Change, k: number): number[] => a.map((x) => rule(x, k));const keepOnly = (a: number[], rule: Keep, k: number): number[] => a.filter((x) => rule(x, k));let a: number[] = lines[1].trim().split(/\s+/).map(Number);const s: number = Number(lines[2]);const out: string[] = [];for (let i = 0; i < s; i++) { const [name, ks] = lines[3 + i].trim().split(/\s+/); const k: number = Number(ks); a = name in CHANGE ? changeAll(a, CHANGE[name], k) : keepOnly(a, KEEP[name], k); out.push(a.length ? a.join(" ") : "-");}console.log(out.join("\n"));
JavaMain.java · 56 줄
import java.io.BufferedReader;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.StringTokenizer;import java.util.function.BiPredicate;import java.util.function.IntBinaryOperator;public class Main { // 함수를 값으로 받는 함수 두 개 static List<Integer> changeAll(List<Integer> a, IntBinaryOperator rule, int k) { List<Integer> b = new ArrayList<>(); for (int x : a) b.add(rule.applyAsInt(x, k)); return b; } static List<Integer> keepOnly(List<Integer> a, BiPredicate<Integer, Integer> rule, int k) { List<Integer> b = new ArrayList<>(); for (int x : a) if (rule.test(x, k)) b.add(x); return b; } public static void main(String[] args) throws Exception { Map<String, IntBinaryOperator> change = new HashMap<>(); change.put("add", (x, k) -> x + k); change.put("mul", (x, k) -> x * k); change.put("mod", Math::floorMod); // %는 음수에서 음수가 나온다. floorMod는 0 이상 k 미만 Map<String, BiPredicate<Integer, Integer>> keep = new HashMap<>(); keep.put("gt", (x, k) -> x > k); keep.put("lt", (x, k) -> x < k); keep.put("div", (x, k) -> x % k == 0); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); in.readLine(); List<Integer> a = new ArrayList<>(); StringTokenizer st = new StringTokenizer(in.readLine()); while (st.hasMoreTokens()) a.add(Integer.parseInt(st.nextToken())); int s = Integer.parseInt(in.readLine().trim()); StringBuilder out = new StringBuilder(); for (int i = 0; i < s; i++) { st = new StringTokenizer(in.readLine()); String name = st.nextToken(); int k = Integer.parseInt(st.nextToken()); a = change.containsKey(name) ? changeAll(a, change.get(name), k) : keepOnly(a, keep.get(name), k); if (a.isEmpty()) { out.append("-\n"); continue; } for (int j = 0; j < a.size(); j++) out.append(j > 0 ? " " : "").append(a.get(j)); out.append('\n'); } System.out.print(out); }}
C#Main.cs · 50 줄
using System;using System.Collections.Generic;using System.Text;class Program{ // 함수를 값으로 받는 함수 두 개 static List<int> ChangeAll(List<int> a, Func<int, int, int> rule, int k) { var b = new List<int>(); foreach (int x in a) b.Add(rule(x, k)); return b; } static List<int> KeepOnly(List<int> a, Func<int, int, bool> rule, int k) { var b = new List<int>(); foreach (int x in a) if (rule(x, k)) b.Add(x); return b; } static void Main() { var change = new Dictionary<string, Func<int, int, int>> { ["add"] = (x, k) => x + k, ["mul"] = (x, k) => x * k, ["mod"] = (x, k) => ((x % k) + k) % k, // %는 음수에서 음수가 나온다 }; var keep = new Dictionary<string, Func<int, int, bool>> { ["gt"] = (x, k) => x > k, ["lt"] = (x, k) => x < k, ["div"] = (x, k) => x % k == 0, }; Console.ReadLine(); var a = new List<int>(); foreach (string t in Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries)) a.Add(int.Parse(t)); int s = int.Parse(Console.ReadLine()); var sb = new StringBuilder(); for (int i = 0; i < s; i++) { string[] p = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); int k = int.Parse(p[1]); a = change.TryGetValue(p[0], out var f) ? ChangeAll(a, f, k) : KeepOnly(a, keep[p[0]], k); sb.Append(a.Count > 0 ? string.Join(" ", a) : "-").Append('\n'); } Console.Write(sb); }}
C++main.cpp · 48 줄
#include <functional>#include <iostream>#include <map>#include <string>#include <vector>using Change = std::function<int(int, int)>;using Keep = std::function<bool(int, int)>;// 함수를 값으로 받는 함수 두 개std::vector<int> changeAll(const std::vector<int> &a, const Change &rule, int k) { std::vector<int> b; for (int x : a) b.push_back(rule(x, k)); return b;}std::vector<int> keepOnly(const std::vector<int> &a, const Keep &rule, int k) { std::vector<int> b; for (int x : a) if (rule(x, k)) b.push_back(x); return b;}int main() { const std::map<std::string, Change> change = { {"add", [](int x, int k) { return x + k; }}, {"mul", [](int x, int k) { return x * k; }}, {"mod", [](int x, int k) { return (x % k + k) % k; }}, // %는 음수에서 음수가 나온다 }; const std::map<std::string, Keep> keep = { {"gt", [](int x, int k) { return x > k; }}, {"lt", [](int x, int k) { return x < k; }}, {"div", [](int x, int k) { return x % k == 0; }}, }; int n, s, k; std::cin >> n; std::vector<int> a(n); for (int &x : a) std::cin >> x; std::cin >> s; std::string name; for (int i = 0; i < s; i++) { std::cin >> name >> k; auto it = change.find(name); a = it != change.end() ? changeAll(a, it->second, k) : keepOnly(a, keep.at(name), k); if (a.empty()) std::cout << '-'; for (std::size_t j = 0; j < a.size(); j++) std::cout << (j ? " " : "") << a[j]; std::cout << '\n'; }}
Cmain.c · 46 줄
#include <stdio.h>#include <string.h>/* 모든 수를 바꾸는 규칙과 남길지 정하는 규칙. 함수 포인터로 넘긴다 */int add(int x, int k) { return x + k; }int mul(int x, int k) { return x * k; }int mod(int x, int k) { return (x % k + k) % k; } /* C의 %는 음수에서 음수가 나온다 */int gt(int x, int k) { return x > k; }int lt(int x, int k) { return x < k; }int divisible(int x, int k) { return x % k == 0; }/* 함수를 값으로 받는 함수 두 개. 남긴 개수를 돌려준다 */int change_all(int *a, int n, int (*rule)(int, int), int k) { for (int i = 0; i < n; i++) a[i] = rule(a[i], k); return n;}int keep_only(int *a, int n, int (*rule)(int, int), int k) { int m = 0; for (int i = 0; i < n; i++) { if (rule(a[i], k)) a[m++] = a[i]; /* 앞으로 당겨 담는다 */ } return m;}int main(void) { struct { const char *name; int (*fn)(int, int); int changes; } rules[] = { {"add", add, 1}, {"mul", mul, 1}, {"mod", mod, 1}, {"gt", gt, 0}, {"lt", lt, 0}, {"div", divisible, 0}, }; int n, s, k, a[300]; char name[8]; scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", &a[i]); scanf("%d", &s); for (int step = 0; step < s; step++) { scanf("%7s %d", name, &k); for (int r = 0; r < 6; r++) { if (strcmp(rules[r].name, name) != 0) continue; n = rules[r].changes ? change_all(a, n, rules[r].fn, k) : keep_only(a, n, rules[r].fn, k); } if (n == 0) puts("-"); for (int i = 0; i < n; i++) printf(i + 1 < n ? "%d " : "%d\n", a[i]); } return 0;}
Craykonmain.cray · 90 줄
// 모든 수를 바꾸는 규칙(x, k → 새 수)더하기(x, k){ 돌려주기 x + k;}곱하기(x, k){ 돌려주기 x * k;}나머지(x, k){ // 크레이콘의 %는 음수에서 음수가 나오니 k를 더해 한 번 더 나눈다 돌려주기 (x % k + k) % k;}// 남길지 정하는 규칙(x, k → 참·거짓)큰것만(x, k){ 돌려주기 x > k;}작은것만(x, k){ 돌려주기 x < k;}배수만(x, k){ 돌려주기 x % k == 0;}// 함수를 값으로 받는 함수 두 개. 크레이콘에는 람다가 없으니 이름으로 넘긴다모두바꾸기(a, 규칙, k){ b = []; 각각 (x 에서 a) { b.넣기(규칙(x, k)); } 돌려주기 b;}골라남기기(a, 규칙, k){ b = []; 각각 (x 에서 a) { 만약 (규칙(x, k)) { b.넣기(x); } } 돌려주기 b;}change = 사전();change["add"] = 더하기;change["mul"] = 곱하기;change["mod"] = 나머지;keep = 사전();keep["gt"] = 큰것만;keep["lt"] = 작은것만;keep["div"] = 배수만;콘솔.줄읽기();a = 콘솔.수들읽기();s = 콘솔.줄읽기().수로변환();반복 (i = 0; i < s; i++){ p = 콘솔.줄읽기().나누기(); k = p[1].수로변환(); 만약 (change.있나(p[0])) { a = 모두바꾸기(a, change[p[0]], k); } 아니면 { a = 골라남기기(a, keep[p[0]], k); } 만약 (a.개수 == 0) { 콘솔.쓰기("-"); } 아니면 { 콘솔.쓰기(a.잇기(" ")); }}