문구점에 공책 n권과 펜 m자루가 있고, 저마다 값이 있다. 공책과 펜에는 주어진 차례대로 1번부터 번호를 붙인다.
오늘은 값이 T 이상인 공책만 d만큼 깎아 준다. 값이 T보다 작은 공책은 값이 그대로이다.
공책 한 권과 펜 한 자루를 묶어 선물 묶음을 만든다. 묶음의 값은 깎은 뒤의 공책 값과 펜 값을 더한 값이다.
다음 세 가지를 차례로 출력하라.
첫째, 깎은 뒤의 공책 값 n개를 주어진 차례대로 한 줄에 출력한다.
둘째, 값이 B 이하인 묶음의 수를 한 줄에 출력하고, 이어서 그런 묶음을 한 줄에 하나씩 공책 번호, 펜 번호, 묶음의 값 차례로 출력한다. 묶음은 공책 번호가 작은 것부터, 공책 번호가 같으면 펜 번호가 작은 것부터 출력한다.
셋째, 값이 B 이하인 묶음들의 값을 같은 값은 한 번만, 작은 값부터 한 줄에 출력한다. 그런 묶음이 없으면 -를 출력한다.
한 줄에 수를 여러 개 출력할 때는 빈칸 하나로 띄운다.
이 문제는 목록에서 새 목록을 만드는 짧은 표현(Python의 내포, 다른 언어의 map·filter 등)을 연습하는 문제이지만, 채점은 출력만 보므로 반복문으로 풀어도 된다.
입력
첫 줄에 n, m, B, T, d가 빈칸 하나로 나뉘어 주어진다. 둘째 줄에 공책 값 n개, 셋째 줄에 펜 값 m개가 빈칸 하나로 나뉘어 주어진다. 1 ≤ n, m ≤ 60, 공책 값과 펜 값은 1 이상 100,000 이하, 1 ≤ B ≤ 200,000, 1 ≤ d < T ≤ 100,000. 모든 수는 정수이다
출력
첫 줄에 깎은 뒤의 공책 값 n개, 둘째 줄에 값이 B 이하인 묶음의 수, 이어서 묶음마다 한 줄씩 공책 번호·펜 번호·묶음의 값, 마지막 줄에 서로 다른 묶음 값들(없으면 -). 수는 쉼표 없이 숫자만 출력
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
Python의 내포는 목록에서 새 목록을 한 줄로 만들어요. 값을 바꾸는 [p - d if p >= T else p for p in notes], 두 겹으로 돌며 거르는 [... for i ... for j ... if ...], 같은 값을 하나로 모으는 집합 내포 {t for ...}가 이 문제의 세 줄이에요. 다른 언어는 같은 일을 다른 도구로 해요. JS·TS는 map·flatMap·filter와 new Set, Java는 스트림의 map·flatMap·filter·distinct·sorted, C#은 LINQ의 Select와 from … from … where … select, Distinct·OrderBy를 써요. C++은 값을 바꿀 때만 transform을 쓰고 두 겹은 for문으로 돌며 std::set에 모아요. C와 크레이콘에는 이런 표현이 없어서 반복문으로 빈 배열·목록에 하나씩 넣고(크레이콘 넣기), 정렬한 뒤(C qsort, 크레이콘 정렬) 바로 앞과 같은 값을 건너뛰어요. 함정 하나: Python 내포에서 if의 자리가 뜻을 바꿔요. for 앞의 a if 조건 else b는 값을 고르는 식이라 원소가 모두 남고, for 뒤의 if는 거르는 조건이라 원소가 줄어요. 예시에서 [p - d for p in notes if p >= T]라고 쓰면 값이 600인 공책이 사라져 첫 줄이 1000 800이 돼요. 함정 둘: for를 두 개 쓰면 왼쪽이 바깥 반복이에요. 차례를 바꾸면 펜이 바깥이 되어 예시의 묶음이 2 2 1100보다 3 1 1100이 먼저 나와요. C# LINQ의 from 두 개도 같은 차례예요. 함정 셋: 중괄호 {...}는 집합, 대괄호 [...]는 목록이에요. 대괄호로 쓰면 같은 값이 그대로 남아 예시의 마지막 줄이 900 1100 1100 1300 1300이 돼요. 함정 넷: JS·TS의 sort()는 비교 함수를 주지 않으면 수를 문자열로 바꿔 사전 차례로 견줘요. 예시의 마지막 줄이 1100 1300 900이 되니 sort((x, y) => x - y)라고 써야 해요. Python의 sorted와 Java의 sorted, C#의 OrderBy, 크레이콘의 정렬은 수를 크기로 견줘요.
Pythonmain.py · 21 줄
import syslines = sys.stdin.read().split("\n")n, m, B, T, d = map(int, lines[0].split())notes = list(map(int, lines[1].split()))pens = list(map(int, lines[2].split()))# 조건식은 for 앞에: 모든 공책이 남고 값만 바뀐다sale = [p - d if p >= T else p for p in notes]# for 두 개는 적힌 차례대로 바깥 → 안쪽, 뒤의 if는 거르는 조건pairs = [(i, j, a + b) for i, a in enumerate(sale, 1) for j, b in enumerate(pens, 1) if a + b <= B]# 집합 내포로 같은 값을 하나로 모은다totals = sorted({t for _, _, t in pairs})out = [" ".join(map(str, sale)), str(len(pairs))]out += [f"{i} {j} {t}" for i, j, t in pairs]out.append(" ".join(map(str, totals)) if totals else "-")print("\n".join(out))
JavaScriptmain.js · 18 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");const [n, m, B, T, d] = lines[0].trim().split(" ").map(Number);const notes = lines[1].trim().split(" ").map(Number);const pens = lines[2].trim().split(" ").map(Number);// map: 모든 공책이 남고 값만 바뀐다const sale = notes.map((p) => (p >= T ? p - d : p));// flatMap으로 두 겹을 한 줄로 펴고, filter로 거른다const pairs = sale .flatMap((a, i) => pens.map((b, j) => [i + 1, j + 1, a + b])) .filter(([, , t]) => t <= B);// Set으로 같은 값을 하나로 모으고, 수로 견주어 정렬한다const totals = [...new Set(pairs.map(([, , t]) => t))].sort((x, y) => x - y);const out = [sale.join(" "), String(pairs.length)];for (const [i, j, t] of pairs) out.push(`${i} ${j} ${t}`);out.push(totals.length > 0 ? totals.join(" ") : "-");console.log(out.join("\n"));
TypeScriptmain.ts · 22 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");const [, , B, T, d]: number[] = lines[0].trim().split(" ").map(Number);const notes: number[] = lines[1].trim().split(" ").map(Number);const pens: number[] = lines[2].trim().split(" ").map(Number);type Pair = [number, number, number];// map: 모든 공책이 남고 값만 바뀐다const sale: number[] = notes.map((p) => (p >= T ? p - d : p));// flatMap으로 두 겹을 한 줄로 펴고, filter로 거른다const pairs: Pair[] = sale .flatMap((a, i) => pens.map((b, j): Pair => [i + 1, j + 1, a + b])) .filter(([, , t]) => t <= B);// Set으로 같은 값을 하나로 모으고, 수로 견주어 정렬한다const totals: number[] = [...new Set(pairs.map(([, , t]) => t))].sort((x, y) => x - y);const out: string[] = [sale.join(" "), String(pairs.length)];for (const [i, j, t] of pairs) out.push(`${i} ${j} ${t}`);out.push(totals.length > 0 ? totals.join(" ") : "-");console.log(out.join("\n"));
JavaMain.java · 41 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.stream.Collectors;import java.util.stream.IntStream;public class Main { static int[] readInts(BufferedReader in) throws IOException { return Arrays.stream(in.readLine().trim().split(" ")).mapToInt(Integer::parseInt).toArray(); } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); int[] head = readInts(in); int n = head[0], m = head[1], B = head[2], T = head[3], d = head[4]; int[] notes = readInts(in); int[] pens = readInts(in); // 스트림의 map: 모든 공책이 남고 값만 바뀐다 int[] sale = Arrays.stream(notes).map(p -> p >= T ? p - d : p).toArray(); // 두 겹은 flatMap으로 펴고 filter로 거른다 int[][] pairs = IntStream.range(0, n).boxed() .flatMap(i -> IntStream.range(0, m).mapToObj(j -> new int[] {i + 1, j + 1, sale[i] + pens[j]})) .filter(p -> p[2] <= B) .toArray(int[][]::new); // distinct로 같은 값을 하나로 모으고 sorted로 정렬한다 int[] totals = Arrays.stream(pairs).mapToInt(p -> p[2]).distinct().sorted().toArray(); StringBuilder out = new StringBuilder(); out.append(Arrays.stream(sale).mapToObj(String::valueOf).collect(Collectors.joining(" "))).append('\n'); out.append(pairs.length).append('\n'); for (int[] p : pairs) { out.append(p[0]).append(' ').append(p[1]).append(' ').append(p[2]).append('\n'); } out.append(totals.length > 0 ? Arrays.stream(totals).mapToObj(String::valueOf).collect(Collectors.joining(" ")) : "-"); System.out.println(out); }}
C#Main.cs · 34 줄
using System;using System.Linq;using System.Text;class Program{ static int[] ReadInts() => Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(int.Parse).ToArray(); static void Main() { int[] head = ReadInts(); int n = head[0], m = head[1], B = head[2], T = head[3], d = head[4]; int[] notes = ReadInts(); int[] pens = ReadInts(); // LINQ Select: 모든 공책이 남고 값만 바뀐다 int[] sale = notes.Select(p => p >= T ? p - d : p).ToArray(); // from 두 개는 적힌 차례대로 바깥 → 안쪽, where는 거르는 조건 var pairs = (from i in Enumerable.Range(0, n) from j in Enumerable.Range(0, m) where sale[i] + pens[j] <= B select (I: i + 1, J: j + 1, Total: sale[i] + pens[j])).ToList(); // Distinct로 같은 값을 하나로 모으고 OrderBy로 정렬한다 int[] totals = pairs.Select(p => p.Total).Distinct().OrderBy(t => t).ToArray(); var sb = new StringBuilder(); sb.Append(string.Join(" ", sale)).Append('\n'); sb.Append(pairs.Count).Append('\n'); foreach (var p in pairs) sb.Append($"{p.I} {p.J} {p.Total}\n"); sb.Append(totals.Length > 0 ? string.Join(" ", totals) : "-").Append('\n'); Console.Write(sb); }}
C++main.cpp · 48 줄
#include <algorithm>#include <array>#include <iostream>#include <set>#include <vector>using namespace std;int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m, B, T, d; cin >> n >> m >> B >> T >> d; vector<int> notes(n), pens(m); for (int &p : notes) cin >> p; for (int &p : pens) cin >> p; // transform: 모든 공책이 남고 값만 바뀐다 vector<int> sale(n); transform(notes.begin(), notes.end(), sale.begin(), [&](int p) { return p >= T ? p - d : p; }); // 두 겹은 for문 두 개로 쓴다 vector<array<int, 3>> pairs; set<int> totals; // 같은 값은 하나만, 늘 정렬된 채로 for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { int t = sale[i] + pens[j]; if (t <= B) { pairs.push_back({i + 1, j + 1, t}); totals.insert(t); } } } for (int i = 0; i < n; i++) cout << (i ? " " : "") << sale[i]; cout << '\n' << pairs.size() << '\n'; for (const auto &p : pairs) cout << p[0] << ' ' << p[1] << ' ' << p[2] << '\n'; if (totals.empty()) { cout << "-\n"; } else { bool first = true; for (int t : totals) { cout << (first ? "" : " ") << t; first = false; } cout << '\n'; } return 0;}
Cmain.c · 52 줄
#include <stdio.h>#include <stdlib.h>#define MAXN 60static int cmp_int(const void *a, const void *b) { int x = *(const int *)a, y = *(const int *)b; return (x > y) - (x < y);}int main(void) { int n, m, B, T, d; static int sale[MAXN], pens[MAXN]; static int pi[MAXN * MAXN], pj[MAXN * MAXN], pt[MAXN * MAXN], totals[MAXN * MAXN]; scanf("%d %d %d %d %d", &n, &m, &B, &T, &d); /* C에는 내포가 없다. 읽으면서 바로 값을 바꾼다 */ for (int i = 0; i < n; i++) { int p; scanf("%d", &p); sale[i] = p >= T ? p - d : p; } for (int j = 0; j < m; j++) scanf("%d", &pens[j]); int count = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (sale[i] + pens[j] <= B) { pi[count] = i + 1; pj[count] = j + 1; pt[count] = sale[i] + pens[j]; totals[count] = pt[count]; count++; } } } for (int i = 0; i < n; i++) printf(i ? " %d" : "%d", sale[i]); printf("\n%d\n", count); for (int k = 0; k < count; k++) printf("%d %d %d\n", pi[k], pj[k], pt[k]); if (count == 0) { printf("-\n"); return 0; } /* 정렬한 뒤, 바로 앞과 같은 값은 건너뛴다 */ qsort(totals, (size_t)count, sizeof(int), cmp_int); for (int k = 0; k < count; k++) { if (k > 0 && totals[k] == totals[k - 1]) continue; printf(k ? " %d" : "%d", totals[k]); } printf("\n"); return 0;}
Craykonmain.cray · 62 줄
첫줄 = 콘솔.수들읽기();n = 첫줄[0];m = 첫줄[1];B = 첫줄[2];T = 첫줄[3];d = 첫줄[4];notes = 콘솔.수들읽기();pens = 콘솔.수들읽기();// 크레이콘에는 내포가 없다. 빈 목록에 하나씩 넣는다sale = [];각각 (p 에서 notes){ 만약 (p >= T) { sale.넣기(p - d); } 아니면 { sale.넣기(p); }}콘솔.쓰기(sale);줄들 = [];totals = [];반복 (i = 0; i < n; i++){ 반복 (j = 0; j < m; j++) { t = sale[i] + pens[j]; 만약 (t <= B) { 줄들.넣기(i + 1 + " " + (j + 1) + " " + t); totals.넣기(t); } }}콘솔.쓰기(줄들.개수);각각 (줄 에서 줄들){ 콘솔.쓰기(줄);}만약 (totals.개수 == 0){ 콘솔.쓰기("-");}아니면{ // 정렬한 뒤, 바로 앞과 같은 값은 건너뛴다 totals.정렬(); 고른것 = [totals[0]]; 반복 (k = 1; k < totals.개수; k++) { 만약 (totals[k] != totals[k - 1]) { 고른것.넣기(totals[k]); } } 콘솔.쓰기(고른것);}