概要
fmt.scan
では、大量入力時に動作が遅いという事なので、入力数$10^5$に対応する関数を書いてみました。
バージョン | 備考 | |
---|---|---|
対応バージョン | 1.6以上 |
Scanner.Buffer 関数の対応バージョン |
AtCoder | 1.6 | 2019年10月01日現在 |
Codeforces | 1.12.6 | 2019年10月01日現在 |
基本的には、
Go 言語で標準入力から読み込む競技プログラミングのアレ --- 改訂第二版
の「bufio
の Scanner
を使う (2) スペース区切りで読み込む」と同じですが、改良して長大文字列をScanner
で読めるようにします。
MaxScanTokenSize
の限界を突破する
デフォルトのScanner
ではMaxScanTokenSize=65536
文字を超える文字列は読み込めなかったのですが、バージョン1.6でScanner.Buffer
関数が追加されました。この関数で使用するバッファと最大読み込み文字数を変更することができます。
作成コード
import (
"os"
"bufio"
"strconv"
)
const MaxBuf = 200100
var buf []byte = make([]byte,MaxBuf)
var sc = bufio.NewScanner(os.Stdin)
func init() {
sc.Split(bufio.ScanWords)
sc.Buffer(buf,MaxBuf)
}
func readString() string {
sc.Scan()
return sc.Text()
}
func readInt() int {
sc.Scan()
r,_ := strconv.Atoi(sc.Text())
return r
}
func readInt64() int64 {
sc.Scan()
r,_ := strconv.ParseInt(sc.Text(),10,64)
return r
}
func readFloat64() float64 {
sc.Scan()
r,_ := strconv.ParseFloat(sc.Text(),64)
return r
}
func init()
は、func main()
の前に実行され、パッケージ変数で初期化できなかった処理を行います。
-
sc.Split(bufio.ScanWords)
- 空白文字区切りで文字列を読み込むよう設定します。
-
sc.Buffer(buf,MaxBuf)
- 前述の通り、読み込みバッファと最大サイズを変更します。
string
型の読み込み
sc.Scan()
で読み込んだ結果をそのまま返します。
int
型の読み込み
n := 1
と書くと、n
はint
型と型推論されます。int
型とint64
型の比較をしようとするとコンパイルエラーとなるため、整数は特に理由がない限りint
型として読み込みたいです。strconv.Atoi
関数を使用して文字列をint
型に変換します。競技プログラミングでは入力が欠落することがないため、エラー処理は行いません。
int64
型の読み込み
int
型のビット数は実装によって違うことがあるため、64ビット整数であることを保証するint64
型で読み込みたいことがあります。strconv.ParseInt
関数を使用します。
float64
型の読み込み
f := 3.14
と書くと、f
はfloat64
型と型推論されます。float32
型を使う理由は特にないため、float64
型の読み込み関数のみ用意します。strconv.ParseFloat
関数を使用します。