Reading a user input and splitting it into two float64 numbers - go

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

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]

Go Test Input and Output from File

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

Image.At returns nil

I'm having an issue. Here is my code:
package main
import (
"math/rand"
"image/draw"
"image/png"
"image/color"
"strconv"
"os"
"time"
"fmt"
)
func genSites(width, height int) ([][]int) {
rand.Seed(time.Now().Unix())
l, err := strconv.Atoi(os.Args[len(os.Args)-2])
if err != nil {
panic(err)
}
sites := make([][]int, l)
for i := range sites {
sites[i] = make([]int, 2)
sites[i][0] = rand.Intn(width)
sites[i][1] = rand.Intn(height)
}
return sites
}
func main() {
inputF, err := os.Open(os.Args[len(os.Args)-3])
if err != nil {
panic(err)
}
defer inputF.Close()
inputR, err := png.Decode(inputF)
if err != nil {
panic(err)
}
input := inputR.(draw.Image)
minx, miny := input.Bounds().Min.X, input.Bounds().Min.Y
maxx, maxy := input.Bounds().Max.X-1, input.Bounds().Max.Y-1
sites := genSites(maxx-minx, maxy-miny)
siteColors := make([][]color.Color, len(sites))
//todo: figure out something better than this
for i := range siteColors {
siteColors[i] = make([]color.Color, (maxx-minx)*(maxy-miny))
}
siteBelongs := make([][]int, maxx - minx)
for x := range siteBelongs {
siteBelongs[x] = make([]int, maxy - miny)
for y := range siteBelongs[x] {
dmin := (maxx-minx)*(maxx-minx) + (maxy-miny)*(maxy-miny)
var smin int
for i, s := range sites {
d := (s[0]-x)*(s[0]-x) + (s[1]-y)*(s[1]-y)
if d > dmin {
smin = i
dmin = d
}
}
siteBelongs[x][y] = smin
siteColors[smin] = append(siteColors[smin], input.At(x+minx, y+miny))
}
}
siteAvgColors := make([]color.Color, len(sites))
for i := range siteAvgColors {
var sR, sG, sB, sA int
for _, val := range siteColors[i] {
fmt.Println(val)
r, g, b, a := val.RGBA()
sR += int(r)
sG += int(g)
sB += int(b)
sA += int(a)
}
siteAvgColors[i] = color.RGBA{
uint8(sR/len(siteColors[i])),
uint8(sG/len(siteColors[i])),
uint8(sB/len(siteColors[i])),
uint8(sA/len(siteColors[i]))}
}
for x := range siteBelongs {
for y := range siteBelongs[x] {
input.Set(minx + x, miny + y, siteAvgColors[siteBelongs[x][y]])
}
}
output, err := os.Create(os.Args[len(os.Args)-1])
if err != nil {
panic(err)
}
defer output.Close()
err = png.Encode(output, input)
if err != nil {
panic(err)
}
}
The error is this:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x4b46e1]
goroutine 1 [running]:
main.main()
/home/victor/programs/goprograms/src/v/imagerandvornoi/main.go:71 +0x7a1
Line 71 is the one that says r, g, b, a := val.RGBA(). That val is inserted at line 63, or siteColors[smin] = append(siteColors[smin], input.At(x+minx, y+miny)), which means that input.At is returning nil. Why? How can I fix this?
This has to do with the semantics of the make() builtin within Go. make is special in that it can take two or three arguments:
make(Type, length) or make(Type, length, capacity). For the former, the length and capacity are set to the same value. If you're going to be assigning values to the slice using append, you're going to want to use the latter form. This is because the two argument form (make(Type, 10)) builds a slice with 10 elements in it already with the zero value, when you use append() it becomes the 11th item.
You're hitting a nil derefernece here because you're using the two-argument version of make with append, and so the first item in the slice is nil.

RGBA to Grayscale in parallel Golang

I have written a program which converts RGBA image to Grayscale sequentially. I'm now trying to convert it so it runs in parallel.
I kind of understand how I need to be doing this but I'm struggling to get started.
Here is what I have so far.
package main
import (
"image"
"image/color"
"image/jpeg"
"log"
"os"
)
var lum float64
type ImageSet interface {
Set(x, y int, c color.Color)
}
func rgbtogray(r uint32, g uint32, b uint32) float64{
lum = 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
return lum
}
func main() {
file, err := os.Open("flower.jpg")
if err != nil {
log.Fatal(err)
}
defer file.Close()
img, err := jpeg.Decode(file)
if err != nil {
log.Fatal(os.Stderr, "%s: %v\n", "flower.jpg", err)
}
channel1 := make(chan float64)
channel2 := make(chan float64)
b := img.Bounds()
imgSet := image.NewRGBA(b)
halfImage := b.Max.X/2
fullImage := b.Max.X
for y := 0; y < b.Max.Y; y++ {
go func() {
for x := 0; x < halfImage; x++ {
oldPixel := img.At(x, y)
r, g, b, _ := oldPixel.RGBA()
channel1 <- rgbtogray(r, g, b)
pixel := color.Gray{uint8(lum / 256)}
imgSet.Set(x, y, pixel)
}
}()
go func() {
for x := halfImage; x< fullImage; x++ {
oldPixel := img.At(x, y)
r, g, b, _ := oldPixel.RGBA()
channel2 <- rgbtogray(r, g, b)
pixel := color.Gray{uint8(lum / 256)}
imgSet.Set(x, y, pixel)
}
}()
}
outFile, err := os.Create("changed.jpg")
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
jpeg.Encode(outFile, imgSet, nil)
}
This runs but just returns a black image. I know the way I'm going about it is wrong but I'm not 100% what route I need to be taking.
My idea is to split the image down the middle, have one channel work on the pixels on the left and one channel work on the pixels on the right. Before moving down to the next y coordinate and so on.
I've tried moving all of the code in my go functions into my rgbatogray function but I was getting multiple errors to do with passing through variables etc. Would it be best to create another function which deals with the splitting etc as I think I calling my go functions should just look something like:
go func() {
channel1 <- rgbtogray(r, g, b)
}()
go func() {
channel2 <- rgbtogray(r, g, b)
}()
I'm unsure what steps I should be taking next on this so any tips and help greatly appreciated.
Here's an implementation of #JimB's suggestion in comments. It exploits the fact of JPEG images being in YCbCr to process the image setting inplace Cb and Cr components to 128 using one goroutine for each of them.
func set(wg *sync.WaitGroup, a []uint8, v uint8) {
for i := 0; i < len(a); i++ {
a[i] = v
}
wg.Done()
}
func gray(i *image.YCbCr) {
var wg sync.WaitGroup
wg.Add(2)
go set(&wg, i.Cb, 128)
go set(&wg, i.Cr, 128)
wg.Wait()
}
func main() {
i, err := jpeg.Decode(os.Stdin)
if err != nil {
log.Fatalf("decoding image: %v", err)
}
gray(i.(*image.YCbCr))
err = jpeg.Encode(os.Stdout, i, nil)
if err != nil {
log.Fatalf("encoding image: %v", err)
}
}
It turned out pretty simple.
Of course it could be extended to create more goroutines (possibly one per available core) assigning slices of Cb & Cr arrays to each for processing.
How about creating a pipeline of pixels read from the image, converted to gray and finally set to a new image, where all steps run concurrently and each step could be internally parallelized?
Then Go's runtime will parallelize the tasks using all available cores.
This implementation works:
package main
import (
"image"
"image/color"
"image/jpeg"
"log"
"os"
"sync"
)
type Setter interface {
Set(x, y int, c color.Color)
}
type Pixel struct {
X, Y int
C color.Color
}
func sendPixels(in image.Image, out chan Pixel) {
b := in.Bounds()
for x := 0; x < b.Max.X; x++ {
for y := 0; y < b.Max.Y; y++ {
out <- Pixel{x, y, in.At(x, y)}
}
}
close(out)
}
func convertToGray(in chan Pixel, out chan Pixel) {
var wg sync.WaitGroup
for p := range in {
wg.Add(1)
go func(p Pixel) {
r, g, b, _ := p.C.RGBA()
l := 0.299*float64(r) + 0.587*float64(g) + 0.114*float64(b)
out <- Pixel{p.X, p.Y, color.Gray{uint8(l / 256)}}
wg.Done()
}(p)
}
wg.Wait()
close(out)
}
func buildImage(in chan Pixel, out Setter, done chan int) {
for p := range in {
out.Set(p.X, p.Y, p.C)
}
close(done)
}
func main() {
i, err := jpeg.Decode(os.Stdin)
if err != nil {
log.Fatalf("decoding image: %v", err)
}
a := make(chan Pixel, 1000)
go sendPixels(i, a)
b := make(chan Pixel, 1000)
go convertToGray(a, b)
c := image.NewRGBA(i.Bounds())
d := make(chan int)
go buildImage(b, c, d)
<-d
err = jpeg.Encode(os.Stdout, c, nil)
if err != nil {
log.Fatalf("encoding image: %v", err)
}
}
Which can be tested running:
go run main.go <in.jpg >out.jpg

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

Resources