Kotlinで高速に標準出力したい
2022-06-27
はじめに
時々、競プロ(AtCoder)をやっています。使用言語は基本的に Kotlin を使っています。とある問題で回答を見ながら Kotlin で実装している時になぜか TLE になっていました。調べたところ、標準出力に使っているprint()
が遅いことが分かりました。
今回は標準出力を高速にするためにしたことのメモです。
PrintWriter を使う
解決方法は単純で、PrintWriter の print or, println メソッドを使うことです。今まで PrintWriter はファイルに対する入出力にしか使えないものだとばかり思っていたので、初耳学でした。
main.kt
import java.io.PrintWriter
fun main(args: Array<String>) {
val fp = PrintWriter(System.out)
fp.print("Hello, World!") // 改行なし
fp.println() // 改行
fp.close()
}
こっちのほうが圧倒的に早いみたいです。
実際に実行時間を計測してみました。出力するものは、0 から 99 のリストを forEach で出力するという単純なもので試してみました。
println()で計測したコード
println.kt
import kotlin.system.measureNanoTime
fun main(args: Array<String>) {
// 0 ~ 99のリスト
val list = (0..99).toList()
val time = measureNanoTime {
list.forEach {
println(it)
}
}
println("時間: $time")
}
PrintWriter の println()で計測したコード
printWriter.kt
import java.io.PrintWriter
import kotlin.system.measureNanoTime
fun main(args: Array<String>) {
// 0 ~ 99のリスト
val list = (0..99).toList()
val fp = PrintWriter(System.out)
val time = measureNanoTime {
list.forEach {
fp.println(it)
}
}
fp.println("時間: $time")
fp.close()
}
それぞれ 5 回ずつ実行してみました。実行時間はナノ秒(ns)です。
回数 | PrintWriter.println | println |
---|---|---|
1 | 135750 | 727917 |
2 | 132500 | 808166 |
3 | 130000 | 781667 |
4 | 137042 | 899125 |
5 | 141291 | 785125 |
平均 | 135316.6 | 800400 |
PrintWriter を使ったほうが大体5.9 倍近く早いみたいです。
最後に
AtCoder には実行時間に制限があるのでこういったテクニックも知っておかないといけませんね。雑にデバッグとしての print は PrintWriter を使わなくても良さそうですが、競プロなら必須かもですね。
それとはじめて Kotlin で実行時間の計測 などをしました。便利な関数があるんですね。
参考サイト
- 【WIP】【競プロ】AtCoder で Kotlin を使う上での注意点とか Tips とか(キャッシュより)
- 色々まとまっていて分かりやすかったのですが、いつの間にかキャッシュも見れなくなっていました;;ですが以前、参考にさせていただいたのでリンクを貼らせて下さい。