Reputation: 5137
I have been giving HackerRank a try where the problems often require reading lines of integers into arrays (slices).
For many of the problems, my parsing code ends up being larger than the algorithmic meat of the solution. For instance, that was the case in Sherlock and Array
Any ideas on how to concisely parse a space-separated line of integers into a slice? fmt.Scanf
doesn't support slices and when using bufio
I get long solutions.
Some requirements:
NOTE: The parser should only consume a single line and not the full input.
Upvotes: 7
Views: 4080
Reputation: 21
func main() {
arr := make([]int, 0)
reader := bufio.NewReaderSize(os.Stdin, 1024*1024)
for {
line, _, err := reader.ReadLine()
if err != nil {
if err == io.EOF {
break
}
panic(err)
}
str := strings.Split(string(line), " ")
for i:=0; i<len(str); i++ {
v, _ := strconv.Atoi(str[i])
arr = append(arr, v)
}
}
fmt.Println(arr)
}
Upvotes: 1
Reputation: 6986
1) read string
2) prepend [
and append ]
3) parse as json into []int?
var input = "1,2,3"
var answer []int
j := []byte(fmt.Sprintf("[%s]",input))
err:= json.Unmarshal(j, &input)
if err != nil {
panic(err)
}
for k,v := range input {
fmt.Printf("Element №%v is %v\n", k,v)
}
also using split strings (https://godoc.org/strings#Split) and https://godoc.org/strconv#ParseInt
input:= "1,2,3"
temp := strings.Split(input, ",")
var answer []int
for _,v := range temp {
i,err := strconv.ParseInt(v)
if err != nill {
panic(err)
}
answer = append(answer, i)
}
UPD: just found that the numbers are SPACE separated. So, this code have to do the thing:
input:= "1 2 3"
temp := strings.Split(input, " ")
var answer []int
for _,v := range temp {
i,err := strconv.ParseInt(v)
if err != nill {
panic(err)
}
answer = append(answer, i)
}
Upvotes: 1
Reputation: 13513
I've used this for those times playing in hackerrank (so concise, but not tested for humans):
func scanInt(n int) []int {
input := make([]int, n)
buffer := make([]interface{}, n)
for i := 0; i < n; i++ {
buffer[i] = &input[i]
}
fmt.Scanln(buffer...)
return input
}
Upvotes: 0
Reputation: 12246
Well, I have done some hackerrank problems too, and here is what I came up with. Typically, problems start with the number of items in the array:
func main() {
var N int
fmt.Scanf("%d", &N)
line := make([]int, N)
for i, _ := range line {
fmt.Scanf("%d", &line[i])
}
// Do something with the values
}
Upvotes: 4
Reputation: 774
You can use fmt.Scanf
, but you need to keep track of the values you're getting.
// a.go
package main
import (
"fmt"
"io"
)
func main() {
var (
next int
nums []int
)
for {
n, err := fmt.Scanf("%d", &next)
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
if n == 0 {
break
}
nums = append(nums, next)
}
fmt.Printf("%#v\n", nums)
}
$ echo "4 8 15 16 23 42" | go run a.go
[]int{4, 8, 15, 16, 23, 42}
Upvotes: 2
Reputation: 11052
// inputs space separated list of integers, outputs []int64
package main
import (
"bufio"
"fmt"
"strconv"
"strings"
)
func main() {
fmt.Println(parse("100 200 300"))
}
func parse(i string) (o []int64) {
// from https://golang.org/pkg/bufio/#example_Scanner_custom
s := bufio.NewScanner(strings.NewReader(i))
splitter := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
advance, token, err = bufio.ScanWords(data, atEOF)
if err == nil && token != nil {
x, err := strconv.ParseInt(string(token), 10, 32)
if err != nil {
panic(err)
}
o = append(o, x)
}
return
}
s.Split(splitter)
for s.Scan() {
}
return o
}
Upvotes: 2