Best way to swap variable values in Go? - go

Is it possible to swap elements like in python?
a,b = b,a
or do we have to use:
temp = a
a = b
b = temp

Yes, it is possible. Assuming a and b have the same type, the example provided will work just fine. For example:
a, b := "second", "first"
fmt.Println(a, b) // Prints "second first"
b, a = a, b
fmt.Println(a, b) // Prints "first second"
Run sample on the playground
This is both legal and idiomatic, so there's no need to use an intermediary buffer.

Yes it is possible to swap elements using multi-value assignments:
i := []int{1, 2, 3, 4}
fmt.Println(i)
i[0], i[1] = i[1], i[0]
fmt.Println(i)
a, b := 1, 2
fmt.Println(a, b)
a, b = b, a // note the lack of ':' since no new variables are being created
fmt.Println(a, b)
Output:
[1 2 3 4]
[2 1 3 4]
1 2
2 1
Example: https://play.golang.org/p/sopFxCqwM1
More details here: https://golang.org/ref/spec#Assignments

Yes you can swap by using
a, b = b, a
So if a = 1 and b= 2,
then after executing
a , b = b, a
you get a = 2 and b = 1
Also, if you write
a, b, a = b, a, b
then it results b = 1 and a = 2

There is a function called Swapper which takes a slice and returns a swap function. This swap function takes 2 indexes and swap the index values in the slice.
package main
import (
"fmt"
"reflect"
)
func main() {
s := []int{1, 2, 3}
fmt.Printf("Before swap: %v\n", s)
swapF := reflect.Swapper(s)
swapF(0, 1)
fmt.Printf("After swap: %v\n", s)
}
Try it
Output
Before swap: [1 2 3]
After swap: [2 1 3]
Yes, you can swap values like python.
a, b := 0, 1
fmt.Printf("Before swap a = %v, b = %v\n", a, b)
b, a = a, b
fmt.Printf("After swap a = %v, b = %v\n", a, b)
Output
Before swap a = 0, b = 1
After swap a = 1, b = 0

you can use ^ option like this...
func swap(nums []int, i, j int) {
nums[i] ^= nums[j]
nums[j] ^= nums[i]
nums[i] ^= nums[j]
}

Related

Error when using pointers to append into slice [][]int

While I was trying to solve a problem "Subset II" from LC, I came across a strange problem. The code generates a power set from a given set.
However, when I run the code it failed because one of the set wasn't correct.
The set [0,3,5,7] replaced by [0,3,5,9] (hence gets appended twice).
I have a print statement (highlighted in code) right before a set gets appended to res, and it prints the correct power set.
The only issue I could think is the use of pointers to append values into a slice, however since it's does not run concurrently I don't see why there would be a race condition.
Appreciate if someone can point out my mistake.
package main
import (
"fmt"
"sort"
)
func ValueCount( nums []int) map[int]int{
hm := make(map[int]int)
for _,v := range(nums){
if c, ok := hm[v]; ok {
hm[v] = c + 1
}else{
hm[v] = 1
}
}
return hm
}
func subsetsWithDup(nums []int) [][]int {
var res [][]int
res = append(res,[]int{})
sort.Ints(nums)
hashMap := ValueCount(nums)
var t []int
printTest(nums, t, &res, hashMap)
return res
}
func printTest(nums []int, t []int, res *[][]int, hm map[int]int) {
if len(nums) == 0 {
return
}
for i:= 0; i < len(nums); {
v := nums[i]
x := nums[i:]
for k:= 0; k< hm[v]; k++ {
var a,b []int
for z:= 0; z<k+1; z++ {
a = append(t,x[z])
}
fmt.Println(a) // <--------- Prints the values that gets appended to res
*res = append(*res, a)
b = a
printTest(nums[i+hm[v]:], b, res, hm)
}
i += hm[v]
}
}
func main(){
n := []int{9,0,3,5,7}
fmt.Println("Find the power set of:", n)
fmt.Println(subsetsWithDup(n))
}
// [0,3,5,7] changes to
// [0,3,5,9] in the output
The bug occurs on line 40:
a = append(t, x[z])
A quick fix would be to change this for loop:
for k := 0; k < hm[v]; k++ {
var a, b []int
for z := 0; z < k+1; z++ {
a = append(t, x[z])
}
fmt.Println(a) // <--------- Prints the values that gets appended to res
*res = append(*res, a)
b = a
printTest(nums[i+hm[v]:], b, res, hm)
}
To this:
for k := 0; k < hm[v]; k++ {
var a, b []int
a = make([]int, len(t))
copy(a, t)
for z := 0; z < k+1; z++ {
a = append(a, x[z])
}
fmt.Println(a) // <--------- Prints the values that gets appended to res
*res = append(*res, a)
b = a
printTest(nums[i+hm[v]:], b, res, hm)
}
It has to do with how Go uses slices as a data structure. When the first argument to the built-in append function was a slice argument, it copied some of the slice's internal data that wasn't intuitive to the programmer. It then modified the argument slice, t, and the newly created slice, a.
I'd recommend reading up on slice internals if you're interested in learning more.
Full program edited:
package main
import (
"fmt"
"sort"
)
func ValueCount(nums []int) map[int]int {
hm := make(map[int]int)
for _, v := range nums {
if c, ok := hm[v]; ok {
hm[v] = c + 1
} else {
hm[v] = 1
}
}
return hm
}
func subsetsWithDup(nums []int) [][]int {
var res [][]int
res = append(res, []int{})
sort.Ints(nums)
hashMap := ValueCount(nums)
var t []int
printTest(nums, t, &res, hashMap)
return res
}
func printTest(nums []int, t []int, res *[][]int, hm map[int]int) {
if len(nums) == 0 {
return
}
for i := 0; i < len(nums); {
v := nums[i]
x := nums[i:]
for k := 0; k < hm[v]; k++ {
var a, b []int
a = make([]int, len(t))
copy(a, t)
for z := 0; z < k+1; z++ {
a = append(a, x[z])
}
fmt.Println(a) // <--------- Prints the values that gets appended to res
*res = append(*res, a)
b = a
printTest(nums[i+hm[v]:], b, res, hm)
}
i += hm[v]
}
}
func main() {
n := []int{9, 0, 3, 5, 7}
fmt.Println("Find the power set of:", n)
fmt.Println(subsetsWithDup(n))
}
New output:
Find the power set of: [9 0 3 5 7]
[0]
[0 3]
[0 3 5]
[0 3 5 7]
[0 3 5 7 9]
[0 3 5 9]
[0 3 7]
[0 3 7 9]
[0 3 9]
[0 5]
[0 5 7]
[0 5 7 9]
[0 5 9]
[0 7]
[0 7 9]
[0 9]
[3]
[3 5]
[3 5 7]
[3 5 7 9]
[3 5 9]
[3 7]
[3 7 9]
[3 9]
[5]
[5 7]
[5 7 9]
[5 9]
[7]
[7 9]
[9]
[[] [0] [0 3] [0 3 5] [0 3 5 7] [0 3 5 7 9] [0 3 5 9] [0 3 7] [0 3 7 9] [0 3 9] [0 5] [0 5 7] [0 5 7 9] [0 5 9] [0 7] [0 7 9] [0 9] [3] [3 5] [3 5 7] [3 5 7 9] [3 5 9] [3 7] [3 7 9] [3 9] [5] [5 7] [5 7 9] [5 9] [7] [7 9] [9]]
Be very careful using (and reusing) slice results - especially when altering those slice values later. Since slices have backing arrays, the referenced data can change in very unexpected ways!
A quick fix to your problem is to copy slice results to a new slice. This ensures changes to the original slice do not introduce bugs (especially in a recursive algorithm).
To copy a slice:
func copyIntSlice(a []int) []int {
c := make([]int, len(a))
copy(c, a) // `a` can now grow/shrink/change without affecting `c`
return c
}
and just call this from your main code:
aCopy := copyIntSlice(a)
*res = append(*res, aCopy)
printTest(nums[i+hm[v]:], aCopy, res, hm)
https://play.golang.org/p/1p8Z4sV9foQ

Capacity of a slice

I am new to Golang and I am following the Tour. The code below produces the following results:
a len=5 cap=5 [0 0 0 0 0]
b len=0 cap=5 []
c len=2 cap=5 [0 0]
d len=3 cap=3 [0 0 0]
How can c have the same cap as b when it was not specified at all?
package main
import "fmt"
func main() {
a := make([]int, 5)
printSlice("a", a)
b := make([]int, 0, 5)
printSlice("b", b)
c := b[:2]
printSlice("c", c)
d := c[2:5]
printSlice("d", d)
}
func printSlice(s string, x []int) {
fmt.Printf("%s len=%d cap=%d %v\n", s, len(x), cap(x), x)
}
Every slice is a pointer type that points to an underlying array. When you make b you create an underlying array to which b points. When you create c by resclicing b you will create a new slice that points to the same underlying array as b.
When you change some entries in b, you will notice that those values get changed in c, too.
There is an official blog entry, that explains all of this in detail: https://blog.golang.org/go-slices-usage-and-internals

How to return the sorted indices for Counting Sort?

I want to return the sorted indices for x array from the Counting Sort algorithm below, it must be simple but I can not figure out how to do that! Can someone please guide me on how to do that in Matlab or Golang or any idomatic c-style demonstration for the algorithm below? thanks a lot in advance.
x=[6 2 5 3 2 2 ];
MAX=10;
n = length(x);
C = zeros(MAX,1); // intialize counting array
for j = 1:n
C(x(j)) = C(x(j)) + 1;
end
z=1;
sorted_x = zeros(n,1); // empty array -container for sorted elements
for j = 1:n;
while ( C(j) >0)
sorted_x(z) = j;
z=z+1;
C(j) = C(j) - 1;
end
end
the code above returns the sorted_x=[2 2 2 3 5 6]
But I want to modify it to also return the sorted_indices=[2 5 6 4 3 1]
Thanks
You can use a map to store the indices -
package main
import "fmt"
func main(){
nums := [6]int{6, 2, 5, 3, 2, 2}
count := make(map[int][]int)
for i, v := range nums {
count[v] = append(count[v], i+1)
}
output := []int{}
for i := 0; i < 10; i++ {
output = append(output, count[i]...)
}
for i := 0; i < len(output); i++ {
fmt.Printf("%d ", nums[output[i]-1])
}
fmt.Println()
fmt.Println("The indices are:")
fmt.Println(output)
}
Output -
2 2 2 3 5 6
The indices are:
[2 5 6 4 3 1]
In matlab the second output value of sort function is the indices. Simply try this:
[sorted, s_ind] = sort(x);
For example, using the Go sort package,
package main
import (
"fmt"
"sort"
)
type AX struct{ A, X []int }
func (ax AX) Len() int {
return len(ax.A)
}
func (ax AX) Swap(i, j int) {
ax.A[i], ax.A[j] = ax.A[j], ax.A[i]
ax.X[i], ax.X[j] = ax.X[j], ax.X[i]
}
func (ax AX) Less(i, j int) bool {
return ax.A[i] < ax.A[j]
}
func sortAX(a []int) (x []int) {
x = make([]int, len(a))
for i := range x {
x[i] = i
}
sort.Stable(AX{A: a, X: x})
return x
}
func main() {
a := []int{6, 2, 5, 3, 2, 2}
fmt.Println("a:", a)
x := sortAX(a)
fmt.Println("a:", a)
fmt.Println("x:", x)
}
Output (Go indices start at 0):
a: [6 2 5 3 2 2]
a: [2 2 2 3 5 6]
x: [1 4 5 3 2 0]
References:
Go: Package sort

Go: read bytes into array

I'm trying to append bytes to an array in the following way:
Go
func readBytes() {
b := make([]byte, 1)
a := [][]byte{}
for i := 0, i < 4, i++ {
conn.Read(b)
a = append(a, b)
fmt.Println(b)
}
fmt.Println(a)
}
Result from fmt.Println(b):
[2]
[5]
[5]
[3]
Result from fmt.Println(a):
[[3], [3], [3], [3]]
Why does it only print out the last byte sent?? Am I missing something?
b is a slice - and you're therefore updating the same underlying array each time you pass it to conn.Read. You can look at this Golang blog post to understand how this works.
Once you call fmt.Println(a) .. each slice is looking at the same underlying array.
You could fix this by instantiating the buffer b in the loop, or using an array instead of a slice.
Here's a working example that re-allocates the b slice inside the loop: http://play.golang.org/p/cN1BE8WSFE
It is essentially (with an int slice):
for i := 0; i < 5; i++ {
b = []int{i, i + 1, i + 2, i + 3, i + 4}
a = append(a, b)
}

What is the point of copying a slice?

What is the point of this snippet of code:
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
for i := range s {
t[i] = s[i]
}
s = t
It's from this page: http://blog.golang.org/go-slices-usage-and-internals, and is supposed to grow a slice. However, above that code snippet is a diagram which depicts a slice as a struct with a pointer, a length, and a capacity. Why does each individual entry have to be copied over instead of something like:
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
t = s[:]
s = t
And if the problem is that the capacity of t is changed to be the same as s, why isn't there another way of setting the pointers to be the same. Or does a slice have a pointer to every single element in the array within its bounds?
Edit: I read a little further and got to this snippet of code:
func CopyDigits(filename string) []byte {
b, _ := ioutil.ReadFile(filename)
b = digitRegexp.Find(b)
c := make([]byte, len(b))
copy(c, b)
return c
}
Its purpose is to stop referencing the file after c is returned by using copy. Does this imply that copy copies the underlying array as well as the slice?
To construct a new, higher capacity underlying array with the same length and values as the old underlying array. The old underlying array will be reclaimed by the garbage collector. For example,
package main
import "fmt"
func main() {
s := []byte{0, 1, 2, 3, 4}[:3]
fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
for i := range s {
t[i] = s[i]
}
s = t
fmt.Printf("s: %p %d %v %d %v\n", &s[0], len(s), s, cap(s), s[:cap(s)])
fmt.Printf("t: %p %d %v %d %v\n", &t[0], len(t), t, cap(t), t[:cap(t)])
}
Output:
s: 0x10500168 3 [0 1 2] 5 [0 1 2 3 4]
t: 0x1052e130 3 [0 0 0] 12 [0 0 0 0 0 0 0 0 0 0 0 0]
s: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
t: 0x1052e130 3 [0 1 2] 12 [0 1 2 0 0 0 0 0 0 0 0 0]
The Go Programming Language Specification
Appending to and copying slices
The function copy copies slice elements from a source src to a
destination dst and returns the number of elements copied. Both
arguments must have identical element type T and must be assignable to
a slice of type []T. The number of elements copied is the minimum of
len(src) and len(dst).
Examples:
var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
var s = make([]int, 6)
var b = make([]byte, 5)
n1 := copy(s, a[0:]) // n1 == 6, s == []int{0, 1, 2, 3, 4, 5}
n2 := copy(s, s[2:]) // n2 == 4, s == []int{2, 3, 4, 5, 4, 5}
n3 := copy(b, "Hello, World!") // n3 == 5, b == []byte("Hello")
If we return a reference to b, we pin the whole underlying array for b. Since b refers to a file, that could easily be megabytes or gigabytes. By returning a new underlying array c, which is the exact size of the number, a few bytes, there will no longer be a reference to the large underlying array for b and it will be reclaimed by the garbage collector. The copy built-in function copies values from b to c. For example,
package main
import "fmt"
func Copy() []byte {
b := []byte{0, 1, 2, 3, 4, 5, 6, 7}
fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
b = b[:2]
fmt.Printf("b: %p %d %v %d %v\n", &b[0], len(b), b, cap(b), b[:cap(b)])
c := make([]byte, len(b))
copy(c, b)
fmt.Printf("c: %p %d %v %d %v\n", &c[0], len(c), c, cap(c), c[:cap(c)])
return c
}
func main() {
d := Copy()
fmt.Printf("d: %p %d %v %d %v\n", &d[0], len(d), d, cap(d), d[:cap(d)])
}
Output:
b: 0x10500168 8 [0 1 2 3 4 5 6 7] 8 [0 1 2 3 4 5 6 7]
b: 0x10500168 2 [0 1] 8 [0 1 2 3 4 5 6 7]
c: 0x10500178 2 [0 1] 2 [0 1]
d: 0x10500178 2 [0 1] 2 [0 1]

Resources