こんにちは。株式会社ヘンリーで開発者をやっているタケハタ です。
ヘンリーは去る2025年11月1日に、Kotlin Fest 2025 にことりスポンサーとしてスポンサーブースを出展しました。
イベント後に報告のエントリー で書いていたのですが、ブースでコンテンツとしてクイズを出題し、多くの方にチャレンジしていただきました。
そのクイズは「【挑戦状】誰が書いたコードか当てまShow!!」と題し、ヘンリーのエンジニア4人が同じ問題に対してコードを書き、どのコードを誰が書いたか当ててもらう というもので、非常に盛り上がり楽しんでいただくことができました。
そこで今回はそのクイズの紹介と答えの解説を書こうと思います。
正答は下の方に書きますので、この記事を読んでいただいているみなさまもぜひチャレンジしてみてください!
出題したクイズ
回答者紹介
まずはコードを書いた回答者4名の紹介です(私も回答しています)。
こちらのプロフィールがどのコードを書いたか当てる上でのヒント になります。
コードを書いた4名
VPoTや創業エンジニア、料理長までいてバラエティに飛んだ面々です。
問題
4人が回答した問題は以下です。
上のコメント部分が問題で、書かれている仕様に沿ってsolve関数を実装し、想定実行結果と同じ内容が出力されるようにします。
fun solve(input: String ): String {
}
fun main() {
val inputs = listOf(
"""
alice 10
bob 7
alice 5
cara 7
dave 7
""" .trimIndent(),
"""
taku 30
haru 20
ken 25
haru 15
ken 10
""" .trimIndent(),
"""
a 5
b 5
c 5
d 1
e 10
""" .trimIndent()
)
for ((i, input) in inputs.withIndex()) {
println("=== Case ${ i + 1 } ===" )
println(solve(input))
println()
}
}
想定実行結果
=== Case 1 ===
1 . alice 15
2 . bob 7
2 . cara 7
2 . dave 7
=== Case 2 ===
1 . haru 35
1 . ken 35
3 . taku 30
=== Case 3 ===
1 . e 10
2 . a 5
2 . b 5
2 . c 5
Collection操作が多く必要で、書き方のクセが出やすい問題になっているところがポイントです。
選択肢(4人のエンジニアが書いたコード)
そしてそれぞれのエンジニアが書いたコードが以下のA〜Dの4つになります。
Aの回答
fun solve(input: String ): String {
var prevScore: Int ? = null
var prevRank = 1
return input.split(" \n " )
.map { it.split(" " ) }
.groupBy({ it[0 ] }, { it[1 ].toInt() })
.mapValues { it.value.sum() }
.toList()
.sortedWith(compareByDescending<Pair <String , Int >> { it.second }.thenBy { it.first })
.mapIndexed { index, (name, score) ->
val rank = if (prevScore == null || prevScore > score) {
index + 1
} else {
prevRank
}
(rank to " $name $score " ).also {
prevScore = score
prevRank = rank
}
}.takeWhile { it.first <= 3 }
.joinToString(" \n " ) {
" ${ it.first} . ${ it.second} "
}
}
Bの回答
fun solve(input: String ): String {
val rankingList = input.lineSequence().map { line ->
val array = line.split(" " )
Pair (array[0 ], array[1 ])
}.groupingBy {
it.first
}.fold(0 ) { sum, (_, score) ->
sum + score.toInt()
}.toList().sortedWith(
compareByDescending<Pair <String , Int >> { it.second }.thenBy { it.first }
)
return buildString {
var rank = 0
var lastScore = 0
rankingList.forEachIndexed { index, (name, score) ->
if (lastScore != score) {
rank = index + 1
}
if (rank > 3 ) {
return @forEachIndexed
}
appendLine(" $rank . $name $score " )
lastScore = score
}
}
}
Cの回答
fun solve(input: String ): String {
val scoreMap = buildMap<String , Int > {
input.lineSequence().forEach {
val (name, score) = it.split(' ' , limit = 2 )
set (name, getOrDefault(name, 0 ) + score.toInt())
}
}
val rankingMap = scoreMap
.asIterable()
.sortedWith(compareByDescending<Map .Entry <String , Int >> { it.value }.thenBy { it.key })
.groupBy({ it.value }, { it.key })
val topScorers = sequence<Triple <Int , String , Int >> {
var rank = 1
for ((score, names) in rankingMap) {
val competitionRank = rank
for (name in names) {
yield(Triple (competitionRank, name, score))
rank++
}
}
}
return topScorers
.takeWhile { (rank, _, _) -> rank <= 3 }
.joinToString(" \n " ) { (rank, name, score) -> " $rank . $name $score " }
}
Dの回答
import java.util.TreeSet
typealias Name = String
typealias Score = Int
fun solve(input: String ): String {
data class Entry (val name: Name, val score: Score)
data class RankedEntry(val rank: Int , val entry: Entry )
class Ranking : TreeSet<Entry >(
compareByDescending<Entry > { it.score }
.thenBy { it.name }
)
tailrec fun aggregateScores(
remaining: List <String >,
scoreMap: HashMap <Name, Score> = HashMap ()
): HashMap <Name, Score> {
if (remaining.isEmpty()) return scoreMap
val line = remaining.first().trim()
if (line.isNotBlank()) {
val (name, scoreStr) = line.split(' ' )
val score = scoreStr.toInt()
scoreMap[name] = (scoreMap[name] ?: 0 ) + score
return aggregateScores(
remaining.drop(1 ),
scoreMap
)
}
return aggregateScores(remaining.drop(1 ), scoreMap)
}
val scoreMap = aggregateScores(input.lines())
val ranking = scoreMap
.map { (name, score) -> Entry (name, score) }
.toCollection(Ranking())
return ranking
.foldIndexed(listOf<RankedEntry>()) { index, acc, entry ->
val rank = if (index > 0 && acc.last().entry.score == entry.score) {
acc.last().rank
} else {
index + 1
}
acc + RankedEntry(rank, entry)
}
.takeWhile { it.rank <= 3 }
.joinToString(" \\ n" ) { " ${ it.rank} . ${ it.entry.name} ${ it.entry.score} " }
}
ここまでが問題になります!
誰がどのコードを書いたかわかりましたか?
正答と解説は下の方にありますので、回答を終えた方は下の方へスクロールしてください!
正答と解説
A: Kengo TODA
AはヘンリーのVPoT、VPoEであるKengo TODAが書いたコードでした。
ポイントとしてはすべての処理をメソッドチェーンで書いている 点ですね。
「ひとこと」に書かれている「全ては流れであり、流れこそが全てである...」で始まる文章がヒントで、すべてがチェーンされているコードは、まるで流れに身を任せているかのような処理を表現しています。
正解された方からは以下のようコメントをいただきました。
全ては流れであり、流れこそが全てであるって書いてあるから全部メソッドチェーンしてる人だと思った
初手split("\n")してるのはJavaっぽいと思ったので、Kotlinを好きって書いてる人とは違うと思った
適切にヒントを読み取って正解されている方も多くいました!
B: タケハタ
Bは私、タケハタが書いたコードでした。
私は一応Kotlinの書籍も過去に出版していて、「ひとこと」にも書いている通り「ワタシ Kotlin チョットデキル」人間として名乗っています。
なのでgroupingByとfoldという普通の人がなかなか知らない関数を使用したり、PairのListをforEachIndexedで回す時に(name, score)で扱ったりと、Kotlinの機能をふんだんに使ったコード に仕上げました。
正解された方からは以下のようコメントをいただきました。
Pairを(name, score)で扱ってるのはKotlin玄人っぽい感じがした
buildStringはKotlin知ってる人っぽい
個人的な想定とは違ったのですが、StringBuilderではなくbuildStringを使うところにKotlinっぽさを感じてわかったという方がかなり多くいました!
やはりKotlin FestではKotlinが好きな方が多く来られていたので、こういった意見も興味深かったです。
C: creasty
Cはヘンリーの創業エンジニアであるcreastyが書いたコードでした。
このコードは正答率も低く、私もポイントがわからなかったのでなにがヒントだったのか後から本人に確認したのですが、なんと「なにも考えてなかった」 という答えが返ってきました!
つまりプロフィールにはヒントがなにもなかった のです。どおりで正答率が低いわけですね。
ちなみに正解された方の中には
とおっしゃっていた方もいたのですが、その方にはコードからなにか感じる予測不能な要素があったのかもしれません。
D: giiita
Dはヘンリーの料理長であるgiiitaが書いたコードでした。
ポイントとしては「ひとこと」にある「業務コードとしてレビューしてもらう気持ちで実装しました」と書かれている通り、コードに丁寧なコメントが書かれている点 ですね。
あとは「好きな言語」にScala を書いていることもポイントで、正解された方からは
というコメントもいただきました。
このコードは正答率も一番高かったです!
あとはなぜか
とおっしゃっていた方もおり、やはりコードにはエンジニアの様々な一面が表現されるものなのだなと、感動を覚えました。
クイズはいかがだったでしょうか?
本記事を読んでいただいたみなさまは、どのコードを誰が書いたかわかったでしょうか?
当日、ブースでこちらのクイズを多くの方が真剣に取り組み、楽しんでいただけました!
かなり難しいクイズになるかと思ったのですが、想像以上に多くの方が正解していて、参加者のみなさまの洞察力に驚きました。
今後もヘンリーでは様々なイベントで、楽しんでいただけるコンテンツを用意していきますので、ブースなどで見かけた際はぜひお立ち寄りください!
告知: Kotlin Fest 2025のアフターイベントを開催します!
最後に告知です。
ヘンリーでは11月25日(火)に、Kotlin Fest 2025の非公式アフターイベントとしてServer-Side Kotlin Night 2025 を開催します!
henry.connpass.com
弊社からKotlin Festに登壇したnabeo も含む、計8名の登壇者でお送りするServer-Side Kotlinのイベントです。
当日直前まで申し込み可能ですので、ぜひこちらもご参加いただければと思います!