Go Test Input and Output from File - go

was trying to determine if there's a way to take a given input and expected output from a file for use in go test.
main.go:
package main
import (
"fmt"
"math"
)
func main() {
var n, m, a float64
fmt.Scanln(&n, &m, &a)
a_in_n_ceil := uint64(math.Ceil(n / a))
a_in_m_ceil := uint64(math.Ceil(m / a))
a_in_n_and_m := a_in_n_ceil * a_in_m_ceil
fmt.Println(a_in_n_and_m)
}
examples:
6 6 4
4
Would it be io.readfile or something similar to grab the first line of input from the examples file and then again for the seconds line of expected output in main_test.go? Guidance is appreciated.

Use os package for file read & write
To read from file : os.ReadFile(path_to_file)
To write file : os.WriteFile("output.txt", data_in_byte_array, file_permission)
package main
import (
"fmt"
"math"
"os"
"strconv"
"strings"
)
func check(e error) {
if e != nil {
panic(e)
}
}
func ReadFromFile(path string) []float64 {
dat, err := os.ReadFile(path) // read file contents
check(err)
stringArr := strings.Split(string(dat)," ")
var numbers []float64
for _, arg := range stringArr {
if n, err := strconv.ParseFloat(arg, 64); err == nil {
numbers = append(numbers, n)
}
}
return numbers // return file contents in required format (in this case []float64)
}
func WriteFile(data string) error{
err := os.WriteFile("output.txt", []byte(data), 0644)
if err != nil {
return err
}
return nil
}
func main(){
var n, m, a float64
numbers := ReadFromFile("input.txt")
fmt.Println(numbers)
n = numbers[0]
m = numbers[1]
a = numbers[2]
a_in_n_ceil := uint64(math.Ceil(n / a))
a_in_m_ceil := uint64(math.Ceil(m / a))
a_in_n_and_m := a_in_n_ceil * a_in_m_ceil
fmt.Println(a_in_n_and_m) // print to console
err = WriteFile(fmt.Sprint(a_in_n_and_m)) // write output to a file
if err != nil {
fmt.Println("Error in file write : ", err)
}
}
input.txt
6 6 4
output.txt
4

Related

Read line of numbers in Go

I have the following input, where on the first line is N - count of numbers, and on the second line N numbers, separated by space:
5
2 1 0 3 4
In Python I can read numbers without specifying its count (N):
_ = input()
numbers = list(map(int, input().split()))
How can I do the same in Go? Or I have to know exactly how many numbers are?
You can iterate through a file line-by-line using bufio, and the strings module can split a string into a slice. So that gets us something like:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
readFile, err := os.Open("data.txt")
defer readFile.Close()
if err != nil {
fmt.Println(err)
}
fileScanner := bufio.NewScanner(readFile)
fileScanner.Split(bufio.ScanLines)
for fileScanner.Scan() {
// get next line from the file
line := fileScanner.Text()
// split it into a list of space-delimited tokens
chars := strings.Split(line, " ")
// create an slice of ints the same length as
// the chars slice
ints := make([]int, len(chars))
for i, s := range chars {
// convert string to int
val, err := strconv.Atoi(s)
if err != nil {
panic(err)
}
// update the corresponding position in the
// ints slice
ints[i] = val
}
fmt.Printf("%v\n", ints)
}
}
Which given your sample data will output:
[5]
[2 1 0 3 4]
Since you know the delimiter and you only have 2 lines, this is also a more compact solution:
package main
import (
"fmt"
"os"
"regexp"
"strconv"
"strings"
)
func main() {
parts, err := readRaw("data.txt")
if err != nil {
panic(err)
}
n, nums, err := toNumbers(parts)
if err != nil {
panic(err)
}
fmt.Printf("%d: %v\n", n, nums)
}
// readRaw reads the file in input and returns the numbers inside as a slice of strings
func readRaw(fn string) ([]string, error) {
b, err := os.ReadFile(fn)
if err != nil {
return nil, err
}
return regexp.MustCompile(`\s`).Split(strings.TrimSpace(string(b)), -1), nil
}
// toNumbers plays with the input string to return the data as a slice of int
func toNumbers(parts []string) (int, []int, error) {
n, err := strconv.Atoi(parts[0])
if err != nil {
return 0, nil, err
}
nums := make([]int, 0)
for _, p := range parts[1:] {
num, err := strconv.Atoi(p)
if err != nil {
return n, nums, err
}
nums = append(nums, num)
}
return n, nums, nil
}
The output out be:
5: [2 1 0 3 4]

Reading a user input and splitting it into two float64 numbers

I have a function to read a single float64 from stdin:
func readFloat() float64 {
scanner := bufio.NewScanner(os.Stdin)
for {
scanner.Scan()
in := scanner.Text()
n, err := strconv.ParseFloat(in, 64)
if err == nil {
return n
} else {
fmt.Println("ERROR:", err)
fmt.Print("\nPlease enter a valid number: ")
}
}
}
I would like to modify this to read two floating point numbers for e.g.
func main() {
fmt.Print("\nEnter x, y coordinates for point1: ")
x1, y1 := readFloat()
Problem I am facing is splitting scanner.Text(). There is a function scanner.Split() but cannot understand how to use it.
Any possible solutions would be helpful.
I would probably go with fmt.Sscanf here
package main
import (
"fmt"
)
func main() {
testCases := []string{"1,2", "0.1,0.2", "1.234,2.234"}
var a, b float64
for _, s := range testCases {
_, err := fmt.Sscanf(s, "%f,%f", &a, &b)
if err != nil {
panic(err)
}
fmt.Printf("Got %f, %f\n", a, b)
}
}
output:
Got 1.000000, 2.000000
Got 0.100000, 0.200000
Got 1.234000, 2.234000
https://play.golang.org/p/7ATyjlkPhnD
Use strings.Split:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func readFloat() (float64, float64) {
scanner := bufio.NewScanner(os.Stdin)
for {
scanner.Scan()
in := scanner.Text()
parts := strings.Split(in, ",")
x, err := strconv.ParseFloat(parts[0], 64)
if err != nil {
fmt.Println("ERROR:", err)
fmt.Print("\nPlease enter a valid number: ")
}
y, err := strconv.ParseFloat(parts[1], 64)
if err != nil {
fmt.Println("ERROR:", err)
fmt.Print("\nPlease enter a valid number: ")
}
return x, y
}
}
func main() {
fmt.Print("\nEnter x, y coordinates for point1: ")
x1, y1 := readFloat()
fmt.Println(x1, y1)
}
Using it:
$ go run main.go
Enter x, y coordinates for point1: 1.2,3.4
1.2 3.4

Read space separated integers from stdin into int slice

I'm trying to read from stdin two lines of an unknown number of space-separated integers. I would like to store each lines ints into their own int slice.
For example, my input may look like this:
1 2 3
4 5 6
and I want to read this into two []int:
[1,2,3]
[4,5,6]
This is what I have so far. scanner.Scan() is giving me the line, but I'm not sure how to convert that into a []int:
package main
import (
"fmt"
"os"
"bufio"
)
func main() {
var firstLine []int
var secondLine []int
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
t := scanner.Text()
}
}
For example,
numbers.go:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func numbers(s string) []int {
var n []int
for _, f := range strings.Fields(s) {
i, err := strconv.Atoi(f)
if err == nil {
n = append(n, i)
}
}
return n
}
func main() {
var firstLine, secondLine []int
scanner := bufio.NewScanner(os.Stdin)
for i := 1; i <= 2 && scanner.Scan(); i++ {
switch i {
case 1:
firstLine = numbers(scanner.Text())
case 2:
secondLine = numbers(scanner.Text())
}
}
fmt.Println(firstLine)
fmt.Println(secondLine)
}
Output:
$ go run numbers.go
1 2 3
4 5 6
[1 2 3]
[4 5 6]
$
If you are looking for code to read input to solve problems in hackathons, here is your best solution
package main
import (
"bufio"
"os"
"fmt"
)
func main() {
reader := bufio.NewReader(os.Stdin)
a:= read(reader,100000)
fmt.Println(a)
}
func read (reader *bufio.Reader, n int)([]uint32) {
a := make([]uint32, n)
for i:=0; i<n; i++ {
fmt.Fscan(reader, &a[i])
}
return a
}
So, this is what I ended up doing. There is likely a more idiomatic way of solving it, though.
package main
import (
"fmt"
"os"
"bufio"
"strings"
"strconv"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
parts := strings.Split(scanner.Text(), " ")
lineOne := createIntSlice(parts)
scanner.Scan()
parts = strings.Split(scanner.Text(), " ")
lineTwo := createIntSlice(parts)
fmt.Println(lineOne)
fmt.Println(lineTwo)
}
func createIntSlice(nums []string) []int {
var r []int
for _, v := range nums {
i, _ := strconv.Atoi(v)
r = append(r, i)
}
return r
}
For another option, you can implement fmt.Scanner:
package main
import (
"bytes"
"fmt"
)
type slice struct {
tok []int
}
func (s *slice) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool { return r != '\n' })
if err != nil { return err }
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
b := bytes.NewReader(tok)
for {
var d int
_, err := fmt.Fscan(b, &d)
if err != nil { break }
s.tok = append(s.tok, d)
}
return nil
}
func main() {
var s slice
fmt.Scan(&s)
fmt.Println(s.tok) // [1 2 3]
}
https://golang.org/pkg/fmt#Scanner
A simpler way to Handle taking space separated integers in a slice !!
func StringToIntSlice(inputSequence string) []int {
var slicedIntegerSequence = []int{}
var splittedSequence = strings.Split(inputSequence, " ")
for _, value := range splittedSequence {
intValue, _ := strconv.Atoi(value)
slicedIntegerSequence = append(slicedIntegerSequence, intValue)
}
return slicedIntegerSequence
}
func main() {
var inputSequence string
var convertedSliceOfIntegers = []int{}
scanner := bufio.NewScanner(os.Stdin)
fmt.Println("Enter a Sequence of 10 Integers separated by spaces:")
scanner.Scan()
inputSequence = scanner.Text()
convertedSliceOfIntegers = StringToIntSlice(inputSequence)
}
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
// You receive a string as parameter
// List receives N As a string slice
// Returns N as a string slice
func number(n string) []string {
list := strings.Fields(n)
return list
}
func main() {
scanner := bufio.NewScanner(os.Stdin) //Receiving user data ...
list := make([][]string, 0) // Declare a slice to receive other slices inside it
for scanner.Scan() { // Scrolls all typed data to true
// If the user does not type anything, that is, if he presses Enter an interrupt will occur
if scanner.Text() == "" {
break
} else {
list = append(list, number(scanner.Text())) // Adding the slice inside list
}
}
fmt.Println(list) // print list
}
All data is going and returning as string, but you can convert them to integers easily.

How to make fmt.Scanln() read into a slice of integers

I have a line containing 3 numbers that I want to read from stdin with fmt.Scanln() but this code won't work:
X := make([]int, 3)
fmt.Scanln(X...)
fmt.Printf("%v\n", X)
I get this error message:
cannot use X (type []int) as type []interface {} in function argument
I don't get it.
Idiomatic Go would be:
func read(n int) ([]int, error) {
in := make([]int, n)
for i := range in {
_, err := fmt.Scan(&in[i])
if err != nil {
return in[:i], err
}
}
return in, nil
}
interface{} means nothing. Please don't use it if you don't have to.
For example,
package main
import "fmt"
func intScanln(n int) ([]int, error) {
x := make([]int, n)
y := make([]interface{}, len(x))
for i := range x {
y[i] = &x[i]
}
n, err := fmt.Scanln(y...)
x = x[:n]
return x, err
}
func main() {
x, err := intScanln(3)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%v\n", x)
}
Input:
1 2 3
Output:
[1 2 3]
I think the the correct version should be
X := make([]int, 3)
fmt.Scanln(&X[0], &X[1], &X[2])
fmt.Printf("%v\n", X)
This error message occurs b/c there's no reasonable way to convert []int to []interface{}. Note, this is in reference to a slice. So the syntax your using is correct, but fmt.Scanln expects []interface{}. This has implications outside of pkg fmt.
The reason I've seen given for this is due to Go giving you control over memory layout so it currently has no reasonable way to do the slice conversion. This means you'll need to do the conversion manually before passing it to a function expecting the slice of a given type. For example:
package main
import (
"fmt"
)
func main() {
x := make([]int, 3)
y := make([]interface{}, 3)
y[0] = x[0]
y[1] = x[1]
y[2] = x[2]
fmt.Println(y...)
}
Or something a little more general:
x := make([]int, 3)
y := make([]interface{}, len(x))
for i, v := range x {
y[i] = v
}
fmt.Println(y...)
Regarding your specific issue, see the following:
x := make([]*int, 3)
for i := range x {
x[i] = new(int)
}
y := make([]interface{}, 3)
for i, v := range x {
y[i] = v
}
if _, err := fmt.Scanln(y...); err != nil {
fmt.Println("Scanln err: ", err)
}
for _, v := range y {
val := v.(*int)
fmt.Println(*val)
}
I saw in a comment you said the lines can have different lengths. In that case
you can implement your own fmt.Scanner:
package main
import (
"bytes"
"fmt"
)
type slice struct {
tok []int
}
func (s *slice) Scan(state fmt.ScanState, verb rune) error {
tok, err := state.Token(false, func(r rune) bool { return r != '\n' })
if err != nil { return err }
if _, _, err := state.ReadRune(); err != nil {
if len(tok) == 0 {
panic(err)
}
}
b := bytes.NewReader(tok)
for {
var d int
_, err := fmt.Fscan(b, &d)
if err != nil { break }
s.tok = append(s.tok, d)
}
return nil
}
func main() {
var s slice
fmt.Scan(&s)
fmt.Println(s.tok)
}
https://golang.org/pkg/fmt#Scanner

Looking for Go equivalent of scanf

I'm looking for the Go equivalent of scanf().
I tried with following code:
1 package main
2
3 import (
4 "scanner"
5 "os"
6 "fmt"
7 )
8
9 func main() {
10 var s scanner.Scanner
11 s.Init(os.Stdin)
12 s.Mode = scanner.ScanInts
13 tok := s.Scan()
14 for tok != scanner.EOF {
15 fmt.Printf("%d ", tok)
16 tok = s.Scan()
17 }
18 fmt.Println()
19 }
I run it with input from a text with a line of integers.
But it always output -3 -3 ...
And how to scan a line composed of a string and some integers?
Changing the mode whenever encounter a new data type?
The Package documentation:
Package scanner
A general-purpose scanner for UTF-8
encoded text.
But it seems that the scanner is not for general use.
Updated code:
func main() {
n := scanf()
fmt.Println(n)
fmt.Println(len(n))
}
func scanf() []int {
nums := new(vector.IntVector)
reader := bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
i, _ := strconv.Atoi(f)
nums.Push(i)
}
str, err = reader.ReadString('\n')
}
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
}
Improved version:
package main
import (
"bufio"
"os"
"io"
"fmt"
"strings"
"strconv"
"container/vector"
)
func main() {
n := fscanf(os.Stdin)
fmt.Println(len(n), n)
}
func fscanf(in io.Reader) []int {
var nums vector.IntVector
reader := bufio.NewReader(in)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = reader.ReadString('\n')
}
return nums
}
Your updated code was much easier to compile without the line numbers, but it was missing the package and import statements.
Looking at your code, I noticed a few things. Here's my revised version of your code.
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"container/vector"
)
func main() {
n := scanf(os.Stdin)
fmt.Println()
fmt.Println(len(n), n)
}
func scanf(in io.Reader) []int {
var nums vector.IntVector
rd := bufio.NewReader(os.Stdin)
str, err := rd.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = rd.ReadString('\n')
}
return nums
}
I might want to use any input file for scanf(), not just Stdin; scanf() takes an io.Reader as a parameter.
You wrote: nums := new(vector.IntVector), where type IntVector []int. This allocates an integer slice reference named nums and initializes it to zero, then the new() function allocates an integer slice reference and initializes it to zero, and then assigns it to nums. I wrote: var nums vector.IntVector, which avoids the redundancy by simply allocating an integer slice reference named nums and initializing it to zero.
You didn't check the err value for strconv.Atoi(), which meant invalid input was converted to a zero value; I skip it.
To copy from the vector to a new slice and return the slice, you wrote:
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
First, I simply replaced that with an equivalent, the IntVector.Data() method: return nums.Data(). Then, I took advantage of the fact that type IntVector []int and avoided the allocation and copy by replacing that by: return nums.
Although it can be used for other things, the scanner package is designed to scan Go program text. Ints (-123), Chars('c'), Strings("str"), etc. are Go language token types.
package main
import (
"fmt"
"os"
"scanner"
"strconv"
)
func main() {
var s scanner.Scanner
s.Init(os.Stdin)
s.Error = func(s *scanner.Scanner, msg string) { fmt.Println("scan error", msg) }
s.Mode = scanner.ScanInts | scanner.ScanStrings | scanner.ScanRawStrings
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
fmt.Print("token:", tok, "text:", txt)
switch tok {
case scanner.Int:
si, err := strconv.Atoi64(txt)
if err == nil {
fmt.Print(" integer: ", si)
}
case scanner.String, scanner.RawString:
fmt.Print(" string: ", txt)
default:
if tok >= 0 {
fmt.Print(" unicode: ", "rune = ", tok)
} else {
fmt.Print(" ERROR")
}
}
fmt.Println()
}
}
This example always reads in a line at a time and returns the entire line as a string. If you want to parse out specific values from it you could.
package main
import (
"fmt"
"bufio"
"os"
"strings"
)
func main() {
value := Input("Please enter a value: ")
trimmed := strings.TrimSpace(value)
fmt.Printf("Hello %s!\n", trimmed)
}
func Input(str string) string {
print(str)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return input
}
In a comment to one of my answers, you said:
From the Language Specification: "When
memory is allocated to store a value,
either through a declaration or make()
or new() call, and no explicit
initialization is provided, the memory
is given a default initialization".
Then what's the point of new()?
If we run:
package main
import ("fmt")
func main() {
var i int
var j *int
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j)
j = new(int)
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j, "; *j (a value) = ", *j)
}
The declaration var i int allocates memory to store an integer value and initializes the value to zero. The declaration var j *int allocates memory to store a pointer to an integer value and initializes the pointer to zero (a nil pointer); no memory is allocated to store an integer value. We see program output similar to:
i (a value) = 0 ; j (a pointer) = <nil>
The built-in function new takes a type T and returns a value of type *T. The memory is initialized to zero values. The statement j = new(int) allocates memory to store an integer value and initializes the value to zero, then it stores a pointer to this integer value in j. We see program output similar to:
i (a value) = 0 ; j (a pointer) = 0x7fcf913a90f0 ; *j (a value) = 0
The latest release of Go (2010-05-27) has added two functions to the fmt package: Scan() and Scanln(). They don't take any pattern string. like in C, but checks the type of the arguments instead.
package main
import (
"fmt"
"os"
"container/vector"
)
func main() {
numbers := new(vector.IntVector)
var number int
n, err := fmt.Scan(os.Stdin, &number)
for n == 1 && err == nil {
numbers.Push(number)
n, err = fmt.Scan(os.Stdin, &number)
}
fmt.Printf("%v\n", numbers.Data())
}

Resources