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()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 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、Craykon 不写类型,直接传。 当场写出没有名字的函数(lambda)的写法也不同:Python lambda w: len(w),JS·TS·C# w => w.length,Java w -> w.length(),C++ [](const std::string& w) { return (int)w.size(); }。 Craykon 和 C 没有 lambda,所以要定义有名字的函数,再像 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));}