{ }codelper
グループ化キー順P0066

最初の文字でまとめる

英小文字の単語が空白一つずつで区切られた一行が与えられる。
最初の文字が同じ単語どうしをまとめよ。
現れた最初の文字ごとにアルファベット順(a から)で一行ずつ "文字: 単語 単語 …" を出力する。
一つのまとまりの中の単語は入力に出た順に書き、同じ単語が何度も出たら出た回数だけすべて書く。

入力
単語の数 1〜1000、各単語は英小文字 1〜12 文字
出力
現れた最初の文字の数だけの行。
各行に文字、コロン(:)、そして単語ごとに空白一つのあとに単語
例 1 · stdin
banana apple cherry avocado blueberry apple
stdout
a: apple avocado apple
b: banana blueberry
c: cherry
main.py
入力(stdin)

実行すると、これらの行が順に input()・標準入力に渡されます(実行中に入力を求めません)。

$ 準備完了

コードを入力して解くにはパソコンで開いてください。モバイルでは問題と解答を見られます。

ほかの言語では?言語別の解答を見る · 8 言語の解答

まとめるとは「キーがなければ空のリストを作って入れ、そのリストに足す」ことです。
一行での書き方は言語ごとに違います:Python defaultdict(list) または groups.setdefault(c, []).append(w)、Java computeIfAbsent(c, k -> new ArrayList<>()).add(w)、C# は TryGetValue でなければ新しい List を入れる、C++ groups[c].push_back(w)([] が空の vector を作ってくれます)、JS は Map で has を聞いて set(c, [])。
落とし穴:Python groups.get(c, []).append(w)、JS (groups.get(c) ?? []).push(w)、Java getOrDefault(c, new ArrayList<>()).add(w) は新しいリストに入れるだけで辞書には保存しないので、まとまりが空のままです。
二つ目の落とし穴は出力の順番:Python dict・JS Map は最初に出た文字の順に回り、Java HashMap は順番を保証しないので、キーを並べ替えるか TreeMap・SortedDictionary・std::map を使います。
C には辞書がありませんが、最初の文字は 26 種類だけなので文字ごとに枠のある固定の表(head[26])で十分で、a から回れば自然にアルファベット順です。
Craykon は 辞書() の値にリストを入れ(もし (!groups.含む(c)) { groups[c] = []; } のあと groups[c].追加(w))、letters = groups.キー一覧; letters.並べ替え(); で順番をそろえます。

Pythonmain.py · 7 行
from collections import defaultdict groups = defaultdict(list)for w in input().split():    groups[w[0]].append(w)for letter in sorted(groups):    print(f"{letter}: {' '.join(groups[letter])}")
JavaScriptmain.js · 8 行
const words = require("fs").readFileSync(0, "utf8").trim().split(/\s+/);const groups = new Map();for (const w of words) {  if (!groups.has(w[0])) groups.set(w[0], []);  groups.get(w[0]).push(w);}const letters = [...groups.keys()].sort();console.log(letters.map((c) => `${c}: ${groups.get(c).join(" ")}`).join("\n"));
TypeScriptmain.ts · 9 行
import { readFileSync } from "node:fs";const words: string[] = readFileSync(0, "utf8").trim().split(/\s+/);const groups = new Map<string, string[]>();for (const w of words) {  if (!groups.has(w[0])) groups.set(w[0], []);  groups.get(w[0])!.push(w);}const letters: string[] = [...groups.keys()].sort();console.log(letters.map((c) => `${c}: ${groups.get(c)!.join(" ")}`).join("\n"));
JavaMain.java · 20 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.ArrayList;import java.util.List;import java.util.Map;import java.util.TreeMap; public class Main {    public static void main(String[] args) throws IOException {        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));        Map<Character, List<String>> groups = new TreeMap<>();        for (String w : in.readLine().trim().split(" "))            groups.computeIfAbsent(w.charAt(0), k -> new ArrayList<>()).add(w);        StringBuilder out = new StringBuilder();        for (Map.Entry<Character, List<String>> e : groups.entrySet())            out.append(e.getKey()).append(": ").append(String.join(" ", e.getValue())).append('\n');        System.out.print(out);    }}
C#Main.cs · 20 行
using System;using System.Collections.Generic; class Program{    static void Main()    {        var groups = new SortedDictionary<char, List<string>>();        foreach (string w in Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries))        {            if (!groups.TryGetValue(w[0], out var list))            {                list = new List<string>();                groups[w[0]] = list;            }            list.Add(w);        }        foreach (var kv in groups) Console.WriteLine($"{kv.Key}: {string.Join(" ", kv.Value)}");    }}
C++main.cpp · 15 行
#include <iostream>#include <map>#include <string>#include <vector> int main() {    std::map<char, std::vector<std::string>> groups;    std::string w;    while (std::cin >> w) groups[w[0]].push_back(w); // 없는 열쇠는 빈 vector가 생긴다    for (const auto& [letter, list] : groups) {        std::cout << letter << ':';        for (const auto& x : list) std::cout << ' ' << x;        std::cout << '\n';    }}
Cmain.c · 26 行
#include <stdio.h> /* C에는 사전이 없다: 첫 글자가 a~z 26가지뿐이니 글자마다 칸이 있는 고정 표를 쓴다 */static char words[1000][13];static int next_in_group[1000]; int main(void) {    int head[26], tail[26];    for (int c = 0; c < 26; c++) head[c] = tail[c] = -1;    int n = 0;    while (scanf("%12s", words[n]) == 1) {        int c = words[n][0] - 'a';        next_in_group[n] = -1;        if (head[c] < 0) head[c] = n;        else next_in_group[tail[c]] = n;        tail[c] = n;        n++;    }    for (int c = 0; c < 26; c++) {        if (head[c] < 0) continue;        printf("%c:", 'a' + c);        for (int i = head[c]; i >= 0; i = next_in_group[i]) printf(" %s", words[i]);        printf("\n");    }    return 0;}
Craykonmain.cray · 17 行
words = コンソール.行読み().空白除去().分ける();groups = 辞書();それぞれ (w の中 words){    c = w[0];    もし (!groups.含む(c))    {        groups[c] = [];    }    groups[c].追加(w);}letters = groups.キー一覧;letters.並べ替え();それぞれ (c の中 letters){    コンソール.書く(c + ": " + groups[c].つなぐ(" "));}