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.printlnprintln
1135750727917
2132500808166
3130000781667
4137042899125
5141291785125
平均135316.6800400

PrintWriter を使ったほうが大体5.9 倍近く早いみたいです。

最後に

AtCoder には実行時間に制限があるのでこういったテクニックも知っておかないといけませんね。雑にデバッグとしての print は PrintWriter を使わなくても良さそうですが、競プロなら必須かもですね。

それとはじめて Kotlin で実行時間の計測などをしました。便利な関数があるんですね。

参考サイト

Tatsumi0000

Written by Tatsumi0000 モバイル開発が好きなエンジニアのブログです. GitHub

Copyright © 2023, Tatsumi0000 All Rights Reserved.