Why the method printInfo does not see the fields of the structure? - go

I want recieve Word: go Page 8 Num of pages 34, but have:
Number of words:
1
Enter word:
go
Enter page:
8
Enter num of pages:
34
Word:
Page: 0
Num of pages: 0
Process finished with the exit code 0
How can I fix it?
package main
import "fmt"
type Word struct {
word string
page, numOfPage int
}
func (obj *Word) printInfo() {
fmt.Printf("Word: %v\n", obj.word)
fmt.Printf("Page: %v\n", obj.page)
fmt.Printf("Num of pages: %v\n", obj.numOfPage)
}
func inputInfo(obj *Word) {
var (
word string
page, numOfPage int
)
fmt.Println("Enter word: ")
fmt.Scan(&word)
fmt.Println("Enter page: ")
fmt.Scan(&page)
fmt.Println("Enter num of pages: ")
fmt.Scan(&numOfPage)
obj.page = page
obj.word = word
obj.numOfPage = numOfPage
}
func main() {
var n int
fmt.Println("Number of words: ")
fmt.Scan(&n)
slc := make([]Word, n)
for _, elem := range slc {
inputInfo(&elem)
}
for _, elem := range slc {
elem.printInfo()
}
}

Related

How to find sum of integers using recursion(without loops) in Golang?

Program should ask values "number of numbers" and "numbers" for each "number of inputs", answers are sum of squares of these numbers. My code works but it shows answers in wrong order, how to make it work properly? Outputs should be shown after all inputs.
I think its easier to understand this program by reading inputs and outputs:
Enter the number of inputs // output
2 // input
Enter the number of numbers // output
2 // input
Enter the numbers // output
1 2 // input (second ans)
Enter the number of numbers // output
2 // input
Enter the numbers
2 3 // input (first ans)
ans = 13 // ans = 2^2 + 3^2
ans = 5 () // ans = 1^2 + 2^2
MyCode:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Println(`Enter the number of inputs`)
n, _ := reader.ReadString('\n')
n = strings.TrimRight(n, "\r\n")
test_cases, err := strconv.Atoi(n)
if err != nil {
fmt.Println(err)
}
process_test_case(test_cases, reader)
}
func process_test_case(test_cases int, reader *bufio.Reader) {
fmt.Println(`Enter the number of numbers`)
_, _ = reader.ReadString('\n')
fmt.Println(`Enter the numbers`)
input, _ := reader.ReadString('\n')
input = strings.TrimRight(input, "\r\n")
arr := strings.Split(input, " ")
test_cases -= 1
if test_cases != 0 {
process_test_case(test_cases, reader)
}
fmt.Println("ans = ", process_array(arr, 0))
}
func process_array(arr []string, result int) int {
num, _ := strconv.Atoi(arr[0])
if len(arr) > 1 {
next := arr[1:]
if num < 0 {
num = 0
}
result = num*num + process_array(next, result)
return result
} else {
if num >= 0 {
return num * num
}
return 0
}
}
How to find sum of integers using recursion (without loops) in Go?
The program should ask "number of numbers" and "numbers" for each "number of inputs", answers are sum of squares of these numbers.
Here is an answer to the question, a recursive solution in Go:
$ go run sumsq.go
Enter the number of inputs:
2
Enter the number of numbers:
2
Enter the numbers:
1
2
Enter the number of numbers:
2
Enter the numbers:
2
3
Sum of Squares:
5
13
$
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func readInt(r *bufio.Reader) int {
line, err := r.ReadString('\n')
line = strings.TrimSpace(line)
if err != nil {
if len(line) == 0 {
return 0
}
}
i, err := strconv.Atoi(line)
if err != nil {
return 0
}
return i
}
func nSquares(n int, r *bufio.Reader) int {
if n == 0 {
return 0
}
i := readInt(r)
return i*i + nSquares(n-1, r)
}
func nNumbers(n int, r *bufio.Reader, sums *[]int) int {
if n == 0 {
return 0
}
fmt.Println("\nEnter the number of numbers: ")
i := readInt(r)
fmt.Println("Enter the numbers: ")
*sums = append(*sums, nSquares(i, r))
return nNumbers(n-1, r, sums)
}
func nInputs(r *bufio.Reader) []int {
fmt.Println("Enter the number of inputs: ")
i := readInt(r)
sums := make([]int, 0, i)
nNumbers(i, r, &sums)
return sums
}
func sumSqrs(sums []int) {
if len(sums) == 0 {
return
}
fmt.Println(sums[0])
sumSqrs(sums[1:])
}
func main() {
r := bufio.NewReader(os.Stdin)
fmt.Println()
sums := nInputs(r)
fmt.Println("\nSum of Squares:")
sumSqrs(sums)
fmt.Println()
}
I have created a sample code for your scenario. You can modify it by using bufio.NewReader(os.Stdin)
func process_array(arr []string) int {
res := 0
for _, v := range arr {
num, err := strconv.Atoi(v)
if err != nil {
panic(err)
}
fmt.Println("num :", num)
res += num * num
}
return res
}
func process_test_case() int {
fmt.Println(`Enter the number of numbers`)
num := 2
fmt.Println("number of numbers :", num)
fmt.Println(`Enter the numbers`)
input := "1 2"
fmt.Println("the numbers :", input)
arr := strings.Split(input, " ")
res := process_array(arr)
return res
}
func main() {
fmt.Println(`Enter the number of inputs`)
test_cases := 1
fmt.Println("number of inputs :", test_cases)
for test_cases >= 1 {
res := process_test_case()
fmt.Println(res)
test_cases -= 1
}
}
You can run it here : https://go.dev/play/p/zGkAln2ghZp
OR
As commented by #phonaputer you can change the sequence. Return the slice and print it from the end.
I think this code answer your title of the question:
package main
import "fmt"
func SumValues(x int, y ...int) (sum int) {
q := len(y) - 1
sum = y[q - x]
if x < q {
sum += SumValues(x + 1, y...)
}
return sum
}
func main() {
sum := SumValues(0,1,2,3,4,5)
fmt.Println("Sum is:", sum)
}

Find largest score word

package main
import (
"bufio"
"fmt"
"os"
"strings"
)
type word struct {
str string
score int
}
func main() {
fmt.Print("Enter a string of words: ")
reader := bufio.NewReader(os.Stdin)
str, _ := reader.ReadString('\n')
strin := strings.Trim(str, "\n")
high_word := get_word(strin)
fmt.Println(high_word)
}
func get_word(in string) []word {
rune_word := strings.Split(in, " ")
stru_sl := make([]word, len(rune_word))
for i := 0; i < len(rune_word); i++ {
stru_sl[i] = word{str: rune_word[i], score: (get_score(rune_word[i]))}
}
return stru_sl
}
func get_score(in_w string) int {
var num int
score_map := make(map[string]int)
alpha := "abcdefghijklmnopqrstuvwxyz"
alpha_run := strings.Split(alpha, "")
for i, a := range alpha_run {
score_map[a] = i + 1
}
for i := 0; i < len(in_w); i++ {
if m, ok := score_map[string(in_w[i])]; ok {
num += m
}
}
return num
}
I've got the code above that gives me a list of structs corresponding to the words you put in, and its score calculated by adding up positions of each letter in the alphabet (1-26). My next step here is to find the word with the highest score. I can do the swap method and sort the structs, but what's the smartest way to achieve this?
If you want to find only the word with the highest score of course sorting isn't necessary, you can scan linearly and update what is highest on every step.
something like that:
highestScoreWord = words[0];
for i := 1; i < len(words); i++ {
if words[i].score > highestScoreWord.score {
highestScoreWord = words[i];
}
}
return highestScoreWord;

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 pretty print byte array and char array?

In the following code, I'm trying to write a Txt() function to pretty print out my structure. It contains following minor questions in the full code:
How to write one line to initialize Char array by string(line 47)
How to speed up checking Char type without strings function(line 29,30)
How to print out Char array as string(line 32)
How to print out Char as string, maybe use Sprintf("%c"), but it is very slow.(line 34)
full code at: http://play.golang.org/p/nUsg_qbufP
type Char byte
type THeader struct {
Ver int8 // will show 1
Tag Char // will show 'H'
}
type TBody struct {
B1 [3]byte // will show "[0,0,0]"
B2 [4]Char // will show "ABCD"
}
func Txt(t interface{}) (s string) {
val := reflect.ValueOf(t)
typ := val.Type()
fields := typ.NumField()
for i := 0; i < fields; i++ {
sf := typ.Field(i)
valfld := val.Field(i)
vType := valfld.Type()
s += sf.Name + ":" + vType.String() + ":"
if strings.HasSuffix(vType.String(), "Char") {
if strings.HasPrefix(vType.String(), "[") {
v, ok := valfld.Interface().([4]Char)
s += fmt.Sprint(ok, v) + "\n"
} else {
s += fmt.Sprint(valfld.Interface()) + "\n"
}
} else {
s += fmt.Sprint(valfld.Interface()) + "\n"
}
}
return
}
func main() {
th := THeader{1, 'H'}
fmt.Printf("%#v\n", th)
// tb := TBody{B2: [10]Char("ABCD")}
tb := TBody{B2: [4]Char{'A', 'B', 'C', 'D'}}
fmt.Printf("%#v\n", tb)
fmt.Print("Txt(th):\n", Txt(th), "\n")
fmt.Print("Txt(tb):\n", Txt(tb), "\n")
}
This code should answer all except for your 1'st questions which is impossible since a function can't return arrays of varying length and Go has no facility to initialize an array of dynamically derived sizes. You need slices for those. The rest of the code is solveable using idiomatic go with the Stringer interface and no reflection required.
package main
import (
"fmt"
)
type Char byte
type CharSlice []Char
type ByteSlice []byte
func (s CharSlice) String() string {
ret := "\""
for _, b := range s {
ret += fmt.Sprintf("%c", b)
}
ret += "\""
return ret
}
func (s ByteSlice) String() string {
return fmt.Sprintf("%v", []byte(s))
}
type THeader struct {
Ver int8 // will show 1
Tag Char // will show 'H'
}
func (t THeader) String() string {
return fmt.Sprintf("{ Ver: %d, Tag: %c}", t.Ver, t.Tag)
}
type TBody struct {
B1 [3]byte // will show "[0,0,0]"
B2 [4]Char // will show "ABCD"
}
func (t TBody) String() string {
return fmt.Sprintf("{ B1: %s, B2: %s", ByteSlice(t.B1[:]), CharSlice(t.B2[:]))
}
func main() {
th := THeader{1, 'H'}
fmt.Printf("%#v\n", th)
tb := TBody{B2: [4]Char{'A', 'B', 'C', 'D'}}
fmt.Printf("%#v\n", tb)
fmt.Printf("Txt(th):\n%s\n", th)
fmt.Printf("Txt(tb):\n%s\n", tb)
}

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