낱말 n개가 있고, 낱말 하나를 수로 바꾸는 기준이 네 가지 있다.
len은 낱말의 글자 수이다.
vowels는 낱말에 들어 있는 모음 a, e, i, o, u의 개수이다.
kinds는 낱말에 쓰인 서로 다른 글자의 가짓수이다.
last는 낱말의 마지막 글자가 알파벳에서 몇 번째인지이다(a는 1, z는 26).
낱말 목록과 기준 함수 하나를 넘겨받아, 그 기준으로 잰 값이 가장 큰 낱말을 돌려주는 함수를 하나만 만들어 네 기준에 모두 쓴다.
값이 가장 큰 낱말이 여럿이면 입력에서 가장 먼저 나온 낱말을 고른다.
첫 줄에 n과 질문의 수 q가 빈칸 하나로 띄워 주어진다.
둘째 줄에 낱말 n개가 빈칸 하나씩 띄워 주어진다.
이어지는 q줄에 기준 이름이 한 줄에 하나씩 주어진다.
질문마다 고른 낱말과 그 낱말의 값을 빈칸 하나로 띄워 한 줄에 출력하라.
입력
1 ≤ n ≤ 100, 1 ≤ q ≤ 100. 낱말은 영어 소문자로만 된 1글자 이상 20글자 이하의 문자열이고, 같은 낱말이 여러 번 나올 수 있다. 기준 이름은 len, vowels, kinds, last 가운데 하나이다
출력
q줄: 질문마다 고른 낱말과 그 값
예시 1 · stdin
6 4
kiwi banana fig queue papaya jazz
len
vowels
kinds
last
stdout
banana 6
queue 4
kiwi 3
jazz 26
main.py
오류 목록00F8 ↓ · ⇧F8 ↑
입력(stdin)
실행하면 이 줄들이 차례로 input()·표준 입력으로 들어가요(실행 중에 묻지 않아요).
$ 준비됐어요
코드를 입력해 풀려면 PC에서 열어 주세요. 모바일에서는 문제와 풀이를 볼 수 있어요.
다른 언어로는?언어별 풀이 보기 · 8개 언어 풀이
함수를 값처럼 다른 함수에 넘기는 문제예요. 넘길 때는 이름 뒤에 괄호를 붙이지 않아요. Python은 max(words, key=count_vowels)처럼 기준 함수를 받는 내장 함수가 있고, C#도 words.MaxBy(key)가 있어요. 둘 다 값이 같으면 먼저 나온 것을 줘요. 함수를 담는 타입은 언어마다 달라요: TS type Key = (w: string) => number, Java ToIntFunction<String>(메서드는 Main::countVowels로 가리키고 key.applyAsInt(w)로 불러요), C# Func<string, int>, C는 함수 포인터 int (*key)(const char *), C++ std::function<int(const std::string&)>. Python·JS·크레이콘은 타입을 적지 않고 그냥 넘겨요. 이름 없는 함수(람다)를 그 자리에서 만드는 법도 달라요: Python lambda w: len(w), JS·TS·C# w => w.length, Java w -> w.length(), C++ [](const std::string& w) { return (int)w.size(); }. 크레이콘과 C에는 람다가 없어서 이름 있는 함수를 만들어 keys["len"] = 글자수처럼 이름만 써서 담아요. Java Collections.max(words, Comparator.comparingInt(key))와 C++ std::max_element는 견주는 함수를 받고, 값이 같으면 먼저 나온 것을 줘요. 함정 셋: ① 반복문으로 찾을 때 >=로 견주면 값이 같은 낱말이 나올 때마다 바꿔서 마지막 낱말이 남아요(예시의 len이 papaya 6, kinds가 jazz 3으로). >를 써요. ② 정렬해서 맨 끝을 집는 Python sorted(words, key=key)[-1]도 같은 값 가운데 마지막 낱말을 줘요. 정렬은 값이 같은 것들의 원래 차례를 지키기 때문이에요. C++ std::minmax_element(...).second도 가장 큰 것 가운데 마지막을 가리켜요. ③ JS에서 best(words, key(words[0]))처럼 괄호를 붙이면 함수가 아니라 그 자리에서 부른 결과(수)가 넘어가요. best 안에서 그 수를 부르려다 key is not a function 오류로 멈춰요.
Pythonmain.py · 27 줄
def count_vowels(w): return sum(1 for c in w if c in "aeiou")def count_kinds(w): return len(set(w))def last_rank(w): return ord(w[-1]) - ord("a") + 1# 기준 이름으로 함수를 찾는 표. 이름 뒤에 괄호를 붙이지 않는다(부르지 않고 함수 자체를 담는다)KEYS = {"len": len, "vowels": count_vowels, "kinds": count_kinds, "last": last_rank}def best(words, key): # max는 key 함수로 잰 값이 가장 큰 것을 돌려주고, 값이 같으면 먼저 나온 것을 돌려준다 return max(words, key=key)n, q = map(int, input().split())words = input().split()for _ in range(q): key = KEYS[input().strip()] w = best(words, key) print(w, key(w))
JavaScriptmain.js · 28 줄
const lines = require("fs").readFileSync(0, "utf8").split("\n");// 기준 이름으로 함수를 찾는 표. 화살표 함수는 그대로 값이다const KEYS = { len: (w) => w.length, vowels: (w) => [...w].filter((c) => "aeiou".includes(c)).length, kinds: (w) => new Set(w).size, last: (w) => w.charCodeAt(w.length - 1) - "a".charCodeAt(0) + 1,};// 낱말 목록과 기준 함수를 받는다. 더 클 때만(>) 바꾸므로 값이 같으면 먼저 나온 낱말이 남는다function best(words, key) { let top = words[0]; for (const w of words) { if (key(w) > key(top)) top = w; } return top;}const [n, q] = lines[0].trim().split(/\s+/).map(Number);const words = lines[1].trim().split(/\s+/);const out = [];for (let i = 0; i < q; i++) { const key = KEYS[lines[2 + i].trim()]; const w = best(words, key); out.push(w + " " + key(w));}console.log(out.join("\n"));
TypeScriptmain.ts · 32 줄
import { readFileSync } from "node:fs";const lines: string[] = readFileSync(0, "utf8").split("\n");// 함수의 타입: 낱말을 받아 수를 돌려준다type Key = (w: string) => number;// 기준 이름으로 함수를 찾는 표. 화살표 함수는 그대로 값이다const KEYS: Record<string, Key> = { len: (w) => w.length, vowels: (w) => [...w].filter((c) => "aeiou".includes(c)).length, kinds: (w) => new Set(w).size, last: (w) => w.charCodeAt(w.length - 1) - "a".charCodeAt(0) + 1,};// 낱말 목록과 기준 함수를 받는다. 더 클 때만(>) 바꾸므로 값이 같으면 먼저 나온 낱말이 남는다function best(words: string[], key: Key): string { let top: string = words[0]; for (const w of words) { if (key(w) > key(top)) top = w; } return top;}const [n, q]: number[] = lines[0].trim().split(/\s+/).map(Number);const words: string[] = lines[1].trim().split(/\s+/);const out: string[] = [];for (let i = 0; i < q; i++) { const key: Key = KEYS[lines[2 + i].trim()]; const w: string = best(words, key); out.push(w + " " + key(w));}console.log(out.join("\n"));
JavaMain.java · 55 줄
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.Arrays;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.List;import java.util.Map;import java.util.StringTokenizer;import java.util.function.ToIntFunction;public class Main { static int countVowels(String w) { int count = 0; for (char c : w.toCharArray()) if ("aeiou".indexOf(c) >= 0) count++; return count; } static int countKinds(String w) { return (int) w.chars().distinct().count(); } static int lastRank(String w) { return w.charAt(w.length() - 1) - 'a' + 1; } // 낱말 목록과 기준 함수를 받는다. Collections.max는 값이 같으면 먼저 나온 것을 돌려준다 static String best(List<String> words, ToIntFunction<String> key) { return Collections.max(words, Comparator.comparingInt(key)); } public static void main(String[] args) throws IOException { // 함수를 값으로 담는 타입이 ToIntFunction<String>이다. 메서드는 "클래스::이름"으로 가리킨다 Map<String, ToIntFunction<String>> keys = new HashMap<>(); keys.put("len", String::length); keys.put("vowels", Main::countVowels); keys.put("kinds", Main::countKinds); keys.put("last", Main::lastRank); BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); int n = Integer.parseInt(st.nextToken()); int q = Integer.parseInt(st.nextToken()); List<String> words = Arrays.asList(in.readLine().trim().split(" +")); StringBuilder out = new StringBuilder(); for (int i = 0; i < q; i++) { ToIntFunction<String> key = keys.get(in.readLine().trim()); String w = best(words, key); // 담아 둔 함수는 key(w)가 아니라 key.applyAsInt(w)로 부른다 out.append(w).append(' ').append(key.applyAsInt(w)).append('\n'); } System.out.print(out); }}
C#Main.cs · 36 줄
using System;using System.Collections.Generic;using System.Linq;using System.Text;class Program{ static int CountVowels(string w) => w.Count(c => "aeiou".Contains(c)); static int CountKinds(string w) => w.Distinct().Count(); static int LastRank(string w) => w[w.Length - 1] - 'a' + 1; // 낱말 목록과 기준 함수를 받는다. MaxBy는 값이 같으면 먼저 나온 것을 돌려준다 static string Best(string[] words, Func<string, int> key) => words.MaxBy(key); static void Main() { // 함수를 값으로 담는 타입이 Func<string, int>이다(string을 받아 int를 돌려주는 함수) var keys = new Dictionary<string, Func<string, int>> { ["len"] = w => w.Length, ["vowels"] = CountVowels, ["kinds"] = CountKinds, ["last"] = LastRank, }; int q = int.Parse(Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries)[1]); string[] words = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries); var sb = new StringBuilder(); for (int i = 0; i < q; i++) { Func<string, int> key = keys[Console.ReadLine().Trim()]; string best = Best(words, key); sb.Append(best).Append(' ').Append(key(best)).Append('\n'); } Console.Write(sb); }}
C++main.cpp · 39 줄
#include <algorithm>#include <functional>#include <iostream>#include <map>#include <set>#include <string>#include <vector>// 함수를 값으로 담는 타입: 낱말을 받아 int를 돌려주는 것이면 함수든 람다든 담긴다using Key = std::function<int(const std::string&)>;// 낱말 목록과 기준 함수를 받는다. max_element는 값이 같으면 먼저 나온 것을 가리킨다const std::string& best(const std::vector<std::string>& words, const Key& key) { return *std::max_element(words.begin(), words.end(), [&](const std::string& a, const std::string& b) { return key(a) < key(b); });}int main() { std::map<std::string, Key> keys = { {"len", [](const std::string& w) { return (int)w.size(); }}, {"vowels", [](const std::string& w) { return (int)std::count_if(w.begin(), w.end(), [](char c) { return std::string("aeiou").find(c) != std::string::npos; }); }}, {"kinds", [](const std::string& w) { return (int)std::set<char>(w.begin(), w.end()).size(); }}, {"last", [](const std::string& w) { return w.back() - 'a' + 1; }}, }; int n, q; std::cin >> n >> q; std::vector<std::string> words(n); for (auto& w : words) std::cin >> w; for (int i = 0; i < q; i++) { std::string name; std::cin >> name; const Key& key = keys[name]; const std::string& w = best(words, key); std::cout << w << ' ' << key(w) << '\n'; }}
Cmain.c · 61 줄
#include <stdio.h>#include <string.h>static int length_of(const char *w) { return (int)strlen(w);}static int count_vowels(const char *w) { int count = 0; for (; *w; w++) if (strchr("aeiou", *w)) count++; return count;}static int count_kinds(const char *w) { int seen[26] = {0}, count = 0; for (; *w; w++) { if (!seen[*w - 'a']) { seen[*w - 'a'] = 1; count++; } } return count;}static int last_rank(const char *w) { return w[strlen(w) - 1] - 'a' + 1;}/* 함수 포인터 타입: 낱말을 받아 int를 돌려주는 함수를 가리킨다 */typedef int (*key_fn)(const char *);/* 낱말 목록과 기준 함수를 받는다. 더 클 때만(>) 바꾸므로 값이 같으면 먼저 나온 낱말이 남는다 */static const char *best(char words[][21], int n, key_fn key) { const char *top = words[0]; for (int i = 1; i < n; i++) { if (key(words[i]) > key(top)) top = words[i]; } return top;}int main(void) { /* 기준 이름과 함수를 짝지은 표. 함수 이름만 쓰면 그 함수의 주소다 */ const char *names[] = {"len", "vowels", "kinds", "last"}; key_fn keys[] = {length_of, count_vowels, count_kinds, last_rank}; int n, q; static char words[100][21]; scanf("%d %d", &n, &q); for (int i = 0; i < n; i++) scanf("%20s", words[i]); for (int i = 0; i < q; i++) { char name[16]; scanf("%15s", name); for (int k = 0; k < 4; k++) { if (strcmp(name, names[k]) == 0) { const char *w = best(words, n, keys[k]); printf("%s %d\n", w, keys[k](w)); } } } return 0;}
Craykonmain.cray · 64 줄
// 기준 함수 네 개. 크레이콘에는 람다가 없어서 이름 있는 함수로 만든다글자수(w){ 돌려주기 w.길이;}모음수(w){ count = 0; 각각 (c 에서 w) { 만약 ("aeiou".있나(c)) { count++; } } 돌려주기 count;}가짓수(w){ 본것 = 사전(); 각각 (c 에서 w) { 본것[c] = 참; } 돌려주기 본것.개수;}끝글자순번(w){ 돌려주기 글자.코드(w[w.길이 - 1]) - 글자.코드("a") + 1;}// 낱말 목록과 기준 함수를 받는다. 더 클 때만(>) 바꾸므로 값이 같으면 먼저 나온 낱말이 남는다으뜸(낱말들, 기준){ top = 낱말들[0]; 각각 (w 에서 낱말들) { 만약 (기준(w) > 기준(top)) { top = w; } } 돌려주기 top;}// 함수 이름을 괄호 없이 쓰면 함수 자체가 값으로 담긴다keys = 사전();keys["len"] = 글자수;keys["vowels"] = 모음수;keys["kinds"] = 가짓수;keys["last"] = 끝글자순번;첫줄 = 콘솔.수들읽기();q = 첫줄[1];words = 콘솔.줄읽기().공백제거().나누기();반복 (i = 0; i < q; i++){ key = keys[콘솔.줄읽기().공백제거()]; w = 으뜸(words, key); 콘솔.쓰기(w + " " + key(w));}