I have the following code where I have a slice of bytes with the alphabet, I copy this alphabet array in a new variable (cryptkey) and I use a function to shuffle it. The result is that the alphabet and the cryptkey byte slice get shuffled. How can I prevent this from happening?
package main
import (
"fmt"
"math/rand"
)
func main() {
alphabet := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz.")
cryptkey := alphabet
fmt.Println(string(alphabet))
cryptkey = shuffle(cryptkey)
fmt.Println(string(alphabet))
}
func shuffle(b []byte) []byte {
l := len(b)
out := b
for key := range out {
dest := rand.Intn(l)
out[key], out[dest] = out[dest], out[key]
}
return out
}
Result :
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz.
miclOfEInzJNvZe.YuVMCdTbXyqtaLwHGjUrABhog xQPWSpKRkDsF
Playground!
Make a copy. For example,
package main
import (
"fmt"
"math/rand"
)
func main() {
alphabet := []byte("ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz.")
cryptkey := alphabet
fmt.Println(string(alphabet))
cryptkey = shuffle(cryptkey)
fmt.Println(string(alphabet))
}
func shuffle(b []byte) []byte {
l := len(b)
out := append([]byte(nil), b...)
for key := range out {
dest := rand.Intn(l)
out[key], out[dest] = out[dest], out[key]
}
return out
}
Output:
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz.
ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz.
Related
How can we get the digits of num := 658943 in Golang? I need to print each digit value from the given number (num) as integer instead of string.
package main
import "fmt"
func main() {
var (
num = 68932
digits []int
)
// do something with num, insert the result to digits
for _, val := range digits {
fmt.Println(val)
}
}
// expected output
// 6
// 8
// 9
// 3
// 2
You can use strconv
package main
import (
"fmt"
"strconv"
)
func main() {
var (
num = 68932
digits []int
)
s := strconv.Itoa(num)
for _, n := range s {
digits = append(digits, int(n-'0'))
}
for _, val := range digits {
fmt.Println(val)
}
}
https://go.dev/play/p/AHzwHPd7GJC
import (
"io"
"os"
"strings"
"fmt"
)
type rot13Reader struct {
r io.Reader
}
func (rot13 rot13Reader) Read(b []byte) (int, error){
n,err := rot13.r.Read(b)
fmt.Printf("\n%v %v\n",n, err)
const A byte ='A'
const a byte ='a'
for i,x := range b{
if x==0 {
n=i
break
}
switch {
case A<=x && x<a:
tmp := x-A
b[i] = A+((tmp+13)%26)
case a<=x && x<a+26 :
tmp := x-a
b[i] = a+((tmp+13)%26)
}
}
return n, err
}
func main() {
s := strings.NewReader("Lbh penpxrq gur pbqr!")
r := rot13Reader{s}
io.Copy(os.Stdout, &r)
}
The code above outputs
21 <nil>
You cracked the code!
0 EOF
Lbh penpxrq gur pbqr!
I have two questions :
Why is the reader being called twice (the second call returning 0 and EOF)
Why does on the second call, b is back to the original chiper? If it reads 0 character, shouldn't it still be "You cracked the code!"?
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 do I use the fmt.Scanf function in Go to get an integer input from the standard input?
If this can't be done using fmt.Scanf, what's the best way to read a single integer?
http://golang.org/pkg/fmt/#Scanf
All the included libraries in Go are well documented.
That being said, I believe
func main() {
var i int
_, err := fmt.Scanf("%d", &i)
}
does the trick
An alternative that can be a bit more concise is to just use fmt.Scan:
package main
import "fmt"
func main() {
var i int
fmt.Scan(&i)
fmt.Println("read number", i, "from stdin")
}
This uses reflection on the type of the argument to discover how the input should be parsed.
http://golang.org/pkg/fmt/#Scan
Here is my "Fast IO" method for reading positive integers. It could be improved with bitshifts and laying out memory in advance.
package main
import (
"io/ioutil"
"bufio"
"os"
"strconv"
)
func main() {
out := bufio.NewWriter(os.Stdout)
ints := getInts()
var T int64
T, ints = ints[0], ints[1:]
..
out.WriteString(strconv.Itoa(my_num) + "\n")
out.Flush()
}
}
func getInts() []int64 {
//assumes POSITIVE INTEGERS. Check v for '-' if you have negative.
var buf []byte
buf, _ = ioutil.ReadAll(os.Stdin)
var ints []int64
num := int64(0)
found := false
for _, v := range buf {
if '0' <= v && v <= '9' {
num = 10*num + int64(v - '0') //could use bitshifting here.
found = true
} else if found {
ints = append(ints, num)
found = false
num = 0
}
}
if found {
ints = append(ints, num)
found = false
num = 0
}
return ints
}
Golang fmt.Scan is simpler than Golang fmt.Scanf (which is simpler than Clang scanf)
If fmt.Scan errors i.e. if not nil, log & return
1 Read single variable:
import (
"fmt"
"log"
)
var i int
if _, err := fmt.Scan(&i); err != nil {
log.Print(" Scan for i failed, due to ", err)
return
}
fmt.Println(i)
2 Read multiple variables:
import (
"fmt"
"log"
)
var i, j, k int
if _, err := fmt.Scan(&i, &j, &k); err != nil {
log.Print(" Scan for i, j & k failed, due to ", err)
return
}
fmt.Println(i, j, k)
Best of luck
Example from: http://www.sortedinf.com/?q=golang-in-1-hour
You can use fmt.Scanf with a format specifier. The format specifier for the integer is %d. So you can use standard input like below.
func main() {
var someVar int
fmt.Scanf("%d", &someVar)
}
or else you can use fmt.Scan or fmt.Scanln as below.
func main() {
var someVar int
fmt.Scanln(&someVar)
}
You could also use bufio.NewReader to read an integer from the standard input.
The below program:
Prompts for an integer input
Creates a bufio.Reader to read from standard input
Reads input till it encounters a newline character '\n' (Note that this will only read a single integer. Space separated values will not work)
Removes the newline character
Converts string to int
package main
import (
"fmt"
"bufio"
"os"
"strconv"
"strings"
)
func getInt() error {
fmt.Println("Enter an integer")
userInput := bufio.NewReader(os.Stdin)
userVal, err := userInput.ReadString('\n')
if err != nil {
return err
}
input := strings.TrimSpace(userVal)
intVal, err := strconv.Atoi(input)
if err != nil {
return err
}
fmt.Printf("You entered: %d\n", intVal)
return nil
}
func main() {
getInt()
}
Why can't we just use a scanf? just like we use in C? it's working though.
package main
import "fmt"
func main() {
var i int
fmt.Scanf("%d", &i)
fmt.Println(i)
}
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())
}