単語を数えて、はじめて出てきた順に出す。初心者向けの練習によくある問題です。各言語の「辞書」(連想配列・map)に数えて、そのまま回して出すプログラムを10言語で書き、同じ入力で 20回ずつ 動かしました。
$ wordcount b a b c a b
正解は、はじめて出てきた順の b: 3 → a: 2 → c: 1 です。
結果:5通りに分かれた
CODE Polyglot の入門 第10回 の正解表(6件)で、毎朝の検証と同じ Linux の環境で動かした結果です。
| 言語(辞書) | 6件中の正解(20回) | 上の入力の出方(20回) |
|---|---|---|
Python dict・Ruby Hash・PHP 連想配列・Kotlin mutableMapOf | 毎回6件 | 毎回 b → a → c |
C# Dictionary | 毎回6件 | 毎回 b → a → c |
JavaScript オブジェクト {} | 毎回5件 | 毎回 b → a → c |
Java HashMap | 毎回4件 | 毎回 a → b → c |
Go map | 6件が11回、5件が4回、4件が5回 | 18回は正しく、2回は c → b → a |
Rust HashMap | 2〜5件(6件は0回) | 6通りすべての並びが出た |
Swift Dictionary | 2〜5件(6件は0回) | 6通りすべての並びが出た |
5つの性格に分けられます。
1. 入れた順に出ると決まっている(Python・Ruby・PHP・Kotlin)。言語の決まりとして約束されている2. 決まっていないが、今回は入れた順に出た(C#)。Dictionary の順番は約束されていない。要素を消したあとに足すと崩れることがある3. 数字に見えるキーだけ先に並ぶ(JavaScript)。2 10 2 1 を数えると 1: 1 → 2: 2 → 10: 1 になった4. 決まっていないが、毎回同じ順(Java)。毎回同じなので、手元の1回では気づきにくい5. 動かすたびに変わる(Go・Rust・Swift)。わざと毎回変わるように作られている
いちばん危ないのは Go
Go は、20回のうち11回は全件正解でした。手元で1回動かして「通った」と思ってしまう確率が半分以上あります。Rust と Swift は20回とも6件そろわなかったので、すぐに気づけます。
どう直したか
出てきた順を、辞書とは別の並び(リスト・配列)に記録して、その順に取り出します。Go ならこうです。
counts := map[string]int{}
order := []string{} // はじめて出てきた順
for _, w := range words {
if _, ok := counts[w]; !ok {
order = append(order, w)
}
counts[w]++
}
for _, w := range order {
fmt.Printf("%s: %d\n", w, counts[w])
}
Java・Kotlin なら入れた順を保つ LinkedHashMap、JavaScript ならオブジェクトの代わりに Map を使う方法もあります。
まとめ
- 「今回は入れた順に出た」と「入れた順に出ると決まっている」は別のこと
- 順番が大事な処理は、言語の決まりを確かめてから辞書を選ぶ。分からなければ、順番を別に記録する
- 1回のテストで通っても安心できない。この記事の数字は20回ずつ動かした結果です
- 10言語の全プログラムは 入門 第10回 にあります
連載「その書き方、本当に通る?」(全4回)
- 第1回:「2026-02-30」を渡したら、PHP と JavaScript だけが黙って3月2日にした
- 第2回:JavaScript で「月の最終日」を出したら、日本では毎回1日前になった
- 第3回:C# の Normalize(FormKC) が、Docker の中では何もしなかった
- 第4回:辞書の「取り出す順番」を10言語で20回ずつ試したら、5通りの性格に分かれた(この記事)
Analyzegear

