2016-05-28 3 views
5

Ich habe HackerRank einen Versuch geben, wo die Probleme häufig Zeilen von Ganzzahlen in Arrays (Slices) lesen müssen.Kurze und robuste Methode zum Lesen einer Zeile mit Leerzeichen getrennten Ganzzahlen in Go

Für viele der Probleme ist mein Parsing-Code größer als das algorithmische Fleisch der Lösung. Zum Beispiel war das der Fall in Sherlock and Array

Irgendwelche Ideen, wie man eine durch Leerzeichen getrennte Zeile von ganzen Zahlen in eine Scheibe genau analysieren kann? fmt.Scanf unterstützt keine Slices und bei Verwendung von bufio bekomme ich lange Lösungen.

Einige Anforderungen:

  • Sie können nur die Standard-Bibliothek verwenden.
  • Die Lösung sollte prägnant sein, je kürzer desto besser.
  • Fehlerprüfungen sollten nicht übersprungen werden. Ich weiß, dass die Eingabe in HackerRank gut definiert ist und Sie sollten in der Lage sein, Ecken zu schneiden, aber bitte nicht, es ist eine schlechte Übung.
  • Es sollte einigermaßen effizient sein.

HINWEIS: Der Parser sollte nur eine einzige Zeile verbrauchen und nicht den vollen Eingang.

Antwort

1

1) gelesen Zeichenfolge

2) prepend [ und ]

3) parsen als json in [] int append?

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) 
} 

auch mit Split-Strings (https://godoc.org/strings#Split) und 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: gerade gefunden, dass die Zahlen SPACE getrennt sind. So haben dieser Code die Sache zu tun:

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) 
} 
+1

Nizza _abuse_ von json :) Allerdings Strings sind durch Leerzeichen getrennte (nicht durch Komma getrennt) und die volle Linie zu lesen ist ziemlich ineffizient im Raum. – fons

1
// 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 
} 
+0

Ich würde das nicht prägnant nennen, tatsächlich sieht es ähnlich aus wie das, was ich geschrieben habe. – fons

+1

./shrug, wenn Sie kleine Funktionen versuchen, versuchen Sie Ruby :) – Plato

+0

Oder Python, oder Haskell :) Ich würde gerne gehen, aber es ist suck, um mehr Zeit auf die Parsing-Teil als auf das Fleisch des Problems verbringen. – fons

2

Sie fmt.Scanf verwenden können, aber Sie müssen den Überblick über die Werte zu halten, Sie bekommen.

// 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} 
+0

Dies ist die beste Option bisher. Du musst nicht nach n suchen, da du immer einen Fehler bekommst, wenn n! = 1 – fons

+0

Eigentlich bleibe ich korrigiert, das funktioniert nicht, da es keine EOLs und EOFs auseinanderhält, es sollte nur eine Zeile konsumieren . – fons

+0

Sie wollten eine durch Leerzeichen getrennte ** Zeile ** von ganzen Zahlen in eine Scheibe _parieren. – noisypixy

0

ich dies in spielen für die damalige Zeit verwendet haben hackerrank (so prägnant, aber nicht für Menschen getestet):

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 
} 
3

Nun, ich habe hab auch ein paar hackerrank-probleme gemacht, und hier ist was ich mir ausgedacht habe. Typischerweise beginnen Probleme mit der Anzahl der Elemente im 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 
} 
Verwandte Themen