go - Faster input scanning -


i attempting solve spoj question can found here

following solution:

package main  import "fmt" import "bufio" import "os"  func main() {     var n, k int     var num int     var divisible int      in := bufio.newreader(os.stdin)      fmt.fscan(in, &n)     fmt.fscan(in, &k)      n > 0 {         fmt.fscan(in, &num)          if num%k == 0 {             divisible++         }          n--     }      fmt.println(divisible) } 

the code works fine. issue here timeout when execute in spoj.

i first using fmt.scan came across this thread suggested use bufio instead faster input scanning.

but still timeout issue. looping inputs , within loop determine whether input divisible or not. so, believe not loop input scanning that's taking time. how can improve read input faster? or issue somewhere else?

you can use bufio.scanner read lines input.

and since we're reading numbers, can create highly optimized converter number. should avoid using scanner.text() creates string can obtain number raw bytes returned scanner.bytes(). scanner.text() returns same token scanner.bytes() first converts string slower , generates "garbage" , work gc.

so here converter function obtains int raw bytes:

func toint(buf []byte) (n int) {     _, v := range buf {         n = n*10 + int(v-'0')     }     return } 

this toint() works because []byte contains utf-8 encoded byte sequence of string representation of decimal format of number, contains digits in range of '0'..'9' utf-8 encoded bytes mapped one-to-one (one byte used 1 digit). mapping digit byte shift: '0' -> 48, '1' -> 49 etc.

using complete application:

package main  import (     "bufio"     "fmt"     "os" )  func main() {     var n, k, c int     scanner := bufio.newscanner(os.stdin)      scanner.scan()     fmt.sscanf(scanner.text(), "%d %d", &n, &k)      ;n > 0; n-- {         scanner.scan()         if toint(scanner.bytes())%k == 0 {             c++         }     }      fmt.println(c) }  func toint(buf []byte) (n int) {     _, v := range buf {         n = n*10 + int(v-'0')     }     return } 

this solution 4 times faster calling strconv.atoi() example.

notes:

in above solution assumed input valid, contains valid numbers , contains @ least n lines after first (which gives n , k).

if input closed after n+1 lines, can use simplified for (and don't need decrement , rely on n):

for scanner.scan() {     if toint(scanner.bytes())%k == 0 {         c++     } } 

Comments