SPOJ 0450 "Enormous Input Test" INTEST

問題:https://www.spoj.pl/problems/INTEST/

Go言語の標準入力について.

Go言語で標準入力を受けとる方法はいくつかあるみたい.
・fmtのScanf等を使う
・scannerのScannerを使う
・bufioのReaderを使う
・io/ioutilのReadAllを使う


以下それぞれの方法における簡単な例.ちなみにos.Stdinはos.Fileで標準入力を表したものであり,bufio.Readerなどに用いる関数は実装されているのでそのまま使えるはず.os.Stdin.Readを使う手もあるけど面倒くさいので割愛.
・fmtのScanf等を使う

package main

import (
	"fmt"
)

func main() {
	n:=0
	fmt.Scan(&n)
	fmt.Println(n)
}


・scannerのScannerを使う

package main

import (
	"scanner"
	"os"
	"fmt"
)

func main() {
	s scanner.Scanner
	s.Init(os.Stdin)
	s.Scan()
	fmt.Println(s.TokenText())
}


・bufioのReaderを使う

pacage main

import (
	"bufio"
	"os"
	"fmt"
)

func main() {
	in := bufio.NewReader(os.Stdin)
	str := in.ReadString('\n')
	fmt.Println(str)
}


・io/ioutilのReadAllを使う

package main

import (
	"io/ioutil"
	"os"
	"fmt"
)

func main() {
	str := ioutil.ReadAll(os.Stdin)
	fmt.Println(str)
}

SPOJのINTESTでいろいろ試してみたけど最後ioutil.ReadAll以外の処理が遅すぎるらしく,TLEになる.
で,以下Acceptedのコード.ゴルーチンも使ってみたけどゴルーチンを使うとTLEするっぽいので使ってない.

package main

import (
	"os"
	"strconv"
	"bufio"
	"io/ioutil"
)

func run() {
	n := next()
	k := next()
	c := 0
	for i := 0; i < n; i++ {
		x := next()
		if x%k < 1 {
			c++
		}
	}
	printIntln(c)
}

func main() {
	run()
	ioend()
}

var (
	buf []byte
	p   int
	out *bufio.Writer
)

func init() {
	buf, _ = ioutil.ReadAll(os.Stdin)
	p = 0
	out = bufio.NewWriter(os.Stdout)
}

func ioend() {
	out.Flush()
}

func next() int {
	r := 0
	s := 1
	for buf[p] == '\n' || buf[p] == ' ' {
		p++
	}
	if buf[p] == '-' {
		s = -1
		p++
	}
	for '0' <= buf[p] && buf[p] <= '9' {
		r = 10*r + int(buf[p]-'0')
		p++
	}
	return s * r
}

func printIntln(n int) {
	println(strconv.Itoa(n))
}

func println(str string) {
	out.WriteString(str)
	out.WriteString("\n")
}

ゴルーチン導入版.使い方が悪いのかもしれない.

package main

import (
	"os"
	"strconv"
	"bufio"
	"io/ioutil"
)

func run() {
	n := <-in
	k := <-in
	c := 0
	for i := 0; i < n; i++ {
		x := <-in
		if x%k < 1 {
			c++
		}
	}
	printIntln(c)
}

func main() {
	run()
	ioend()
}

var (
	in  chan int
	buf []byte
	out *bufio.Writer
)

func init() {
	in = make(chan int)
	buf, _ = ioutil.ReadAll(os.Stdin)
	go intInput()
	out = bufio.NewWriter(os.Stdout)
}

func ioend() {
	out.Flush()
}

func intInput() {
	p := 0
	getBuf := make(chan byte)
	go func() {
		for p := 0; p < len(buf); p++ {
			getBuf <- buf[p]
		}
		getBuf <- 0
	}()
	for p < len(buf) {
		r := 0
		s := 1
		b := <-getBuf
		for b == '\n' || b == ' ' {
			b = <-getBuf
		}
		if b == '-' {
			s = -1
			b = <-getBuf
		}
		for ; '0' <= b && b <= '9'; b = <-getBuf {
			r = 10*r + int(b-'0')
		}
		in <- s*r
	}
}

func printIntln(n int) {
	println(strconv.Itoa(n))
}

func println(str string) {
	out.WriteString(str)
	out.WriteString("\n")
}