Related
This is a LeetCode problem: 189. Rotate Array:
Given an array, rotate the array to the right by k steps, where k is
non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3
Output: [5,6,7,1,2,3,4]
And here is my solution:
func rotate(nums []int, k int) {
k = k % len(nums)
nums = append(nums[k:],nums[0:k]...)
fmt.Println(nums)
}
It is a straight forward algorithm but it does not work.
I am new to Go. I suppose nums is passed by value and changes to nums won't affect the real nums.
How can I get this right?
In Go, all arguments are passed by value.
A Go slice is represented at runtime by a slice descriptor:
type slice struct {
array unsafe.Pointer
len int
cap int
}
If you change any of the slice descriptor values in a function then communicate the change, typically by returning the changed slice descriptor.
Your rotate function changes the values of the slice num pointer to the underlying array and the slice capacity, so return num.
For example, after I fixed the bugs in your rotate algorithm,
package main
import "fmt"
func rotate(nums []int, k int) []int {
if k < 0 || len(nums) == 0 {
return nums
}
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
r := len(nums) - k%len(nums)
nums = append(nums[r:], nums[:r]...)
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
return nums
}
func main() {
nums := []int{1, 2, 3, 4, 5, 6, 7}
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
nums = rotate(nums, 3)
fmt.Printf("nums %p array %p len %d cap %d slice %v\n", &nums, &nums[0], len(nums), cap(nums), nums)
}
Output:
nums 0xc00000a080 array 0xc00001a1c0 len 7 cap 7 slice [1 2 3 4 5 6 7]
nums 0xc00000a0c0 array 0xc00001a1c0 len 7 cap 7 slice [1 2 3 4 5 6 7]
nums 0xc00000a0c0 array 0xc00001a240 len 7 cap 8 slice [5 6 7 1 2 3 4]
nums 0xc00000a080 array 0xc00001a240 len 7 cap 8 slice [5 6 7 1 2 3 4]
Reference: The Go Blog: Go Slices: usage and internals
Here's a way do rotate a float 32 slice, you can change it for another type.
//RotateF32Slice positive n rotate to the left, negative to right
func RotateF32Slice(slice []float32, n int) (rotateSlice []float32) {
var begin []float32
var end []float32
size := len(slice)
rotateSlice = make([]float32, size)
nAbs := math.Abs(float64(n))
if int(nAbs) > size {
remainder, _ := QuotientAndRemainderF32(float32(n), float32(size))
n = int(remainder)
}
if n != 0 {
if n > 0 {
index := size - n
begin = slice[index:]
end = slice[0:index]
copy(rotateSlice, begin)
copy(rotateSlice[n:], end)
} else {
n = int(nAbs)
index := size - n
begin = slice[n:]
end = slice[0:n]
copy(rotateSlice, begin)
copy(rotateSlice[index:], end)
}
} else {
copy(rotateSlice, slice)
}
return rotateSlice
}
//QuotientAndRemainderF32 Computes the integer quotient and the remainder of the inputs. This function rounds floor(x/y) to the nearest integer towards -inf.
func QuotientAndRemainderF32(x, y float32) (Remainder, Quotient float32) {
Quotient = float32(math.Floor(float64(x / y)))
Remainder = x - y*Quotient
return Remainder, Quotient
}
Solutions
Solution 1 :
func rotate(ar []int,d,n int) []int{
var newArray []int
for i:=0;i<d;i++{
newArray = ar[1:n]
newArray = append(newArray,ar[0])
ar = newArray
}
return ar
}
Solution 2 :
func rotateR(ar []int,d,n int) []int{
ar = append(ar[d:n],ar[0:d]...)
return ar
}
func rotate(nums []int, k int) {
k = k % len(nums)
result := append(nums[len(nums)-k:], nums[:len(nums)-k]...)
for i := 0; i < len(nums); i++ {
nums[i] = result[i]
}
}
Answering this late as i came across this while reading the book "The Go Programming language". It presents a quite elegant algo to use the reverse function and apply it thrice to achieve the desired rotation by k elems. Something like this
// function to rotate array by k elems (3 reverse method)
func rotate(arr []int, k int) {
reverse(arr[:k])
reverse(arr[k:])
reverse(arr)
}
Please note, you will have to write a reverse function. Go does not provide one. This is an O(n) solution and takes O(1) space.
This is my solution to the same hackerrank problem
func rotateLeft(d int32, arr []int32) []int32 {
for ; d > 0 ; d-- {
left := arr[0]
arr = arr[1:]
arr = append(arr, left)
}
return arr
}
for me this worked for many of array rotating but not for hundreds nums[].
func rotate(nums []int, k int) {
for count:=k; count>0; count--{
if len(nums) >= 1 && len(nums) <= 10^5 {
for i:=len(nums)-1; i>0; i--{
nums[i], nums[i-1] = nums[i-1], nums[i]
}
}
}
}
Given an array, rotate the array to the right by k steps, where k is
non-negative.
Example 1:
Input: [1,2,3,4,5,6,7] and k = 3 Output: [5,6,7,1,2,3,4]
Blockquote
First, for k=3, shouldn't be the output [4,5,6,7,1,2,3] ?
For most array operations, it is always simplier to add elements to a newly created array rather than change the source array. If the array is not really large (takes Gigs of memory / billions of items, etc..), you can use a function that adds elements to the newly created array in the order you require and returns new one:
// GO 1.18
func rot[T any](slice []T, k int) (newSlice []T){
l := len(slice)
for i := range slice {
newSlice = append(newSlice, slice[(k+i) % l])
}
return
}
fmt.Printf("Slice %v after rotation %v\n", []int{1,2,3,4,5,6,7}, rot[int]([]int{1,2,3,4,5,6,7}, 3))
//Slice [1 2 3 4 5 6 7] after rotation [4 5 6 7 1 2 3]
If you insist on using "slicing", the code looks like this:
func rotationBySlicing[T any](slice []T, k int) (newSlice []T) {
if len(slice) == 0 {
return slice
}
return append(slice[(k%len(slice)):],slice[0:k%len(slice)]...)
}
fmt.Printf("Array %v after rotation %v\n", []string{}, rotationBySlicing[string]([]string{},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a"}, rotationBySlicing[string]([]string{"a"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a","b"}, rotationBySlicing[string]([]string{"a","b"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a","b","c"}, rotationBySlicing[string]([]string{"a","b","c"},1))
fmt.Printf("Array %v after rotation %v\n", []string{"a", "b", "c", "d"}, rotationBySlicing[string]([]string{"a", "b", "c", "d"},1))
fmt.Printf("Slice %v after rotation %v\n", []int{1,2,3,4,5,6,7}, rotationBySlicing[int]([]int{1,2,3,4,5,6,7}, 3))
Array [] after rotation []
Array [a] after rotation [a]
Array [a b] after rotation [b a]
Array [a b c] after rotation [b c a]
Array [a b c d] after rotation [b c d a]
Array [1 2 3 4 5 6 7] after rotation [4 5 6 7 1 2 3]
Also instruction says:
where k is non-negative
, for completeness the code should handle case when k is less than 0
In my case, I preferred this algorithm below because I wanted to keep slice capacity the same:
// Rotation by keeping the capacity same
func Rotate(nums []int, k int) {
k %= len(nums)
new_array := make([]int, len(nums))
copy(new_array[:k], nums[len(nums)-k:])
copy(new_array[k:], nums[:len(nums)-k])
copy(nums, new_array)
}
Also, I tested it in Leet code and it looks good :)
You can also add a condition at the top of your function to make it ready for negative shifts (rotates),
Whole code again:
func Rotate(nums []int, k int) {
k %= len(nums)
// Condition below is added.
if k < 0 {
k += len(nums)
}
new_array := make([]int, len(nums))
copy(new_array[:k], nums[len(nums)-k:])
copy(new_array[k:], nums[:len(nums)-k])
copy(nums, new_array)
}
This doesn't work because []byte is a slice which is sort of a "pointer to an array". Doing:
func f(v []T) {
v = ... //
}
won't have any observable effect for the caller. Assuming your append way is correct (didn't really check it) you could do something like this:
func rotate(nums []int, k int) {
k = k % len(nums)
temp := append(nums[k:], nums[0:k]...)
copy(nums, temp) // this actually writes to where nums points to
}
func main() {
nums := []int{1,2,3,4,5,6,7}
rotate(nums ,3)
fmt.Println(nums)
}
I am going through Go's official tutorial and have difficulty understanding the difference between Channel and Buffered Channels. The links to the tutorials are https://tour.golang.org/concurrency/2 and https://tour.golang.org/concurrency/3
In the Channel tutorial, Channel c first received the sum of [7, 2, 8] which is 17 and then received the sum of [-9, 4, 0] which is -5. When reading from c, it first output -5 to x and then 17 to y, in LIFO order:
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
c <- sum // send sum to c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:len(s)/2], c)
go sum(s[len(s)/2:], c)
x, y := <-c, <-c // receive from c
fmt.Println(x, y, x+y)
}
(The above output is -5 17 12)
In the Buffered Channel tutorial, the output is 1 2, in FIFO order:
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
fmt.Println(<-ch)
}
Why are they different?
The chnnael c, in your 1st example of unbuffered channel, is not acting as LIFO.
Actually it is happening because of go routines. The go routines executes concurrently.
If you tweak your code to debug, add one extra line in sum to print the sum before sending to channel.
package main
import "fmt"
func sum(s []int, c chan int) {
sum := 0
for _, v := range s {
sum += v
}
fmt.Println("slice:", s)
fmt.Println(sum)
c <- sum // send sum to c
}
func main() {
s := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(s[:2], c)
go sum(s[2:4], c)
go sum(s[4:6], c)
x, y, z := <-c, <-c, <-c // receive from c
fmt.Println(x, y, z, x+y+z)
}
The output is:
slice: [4 0]
4
slice: [7 2]
9
slice: [8 -9]
-1
4 9 -1 12
So, you can see that x receives the 1st number that was sent through channel.
Furthermore, unbuffered channels sends data directly to receiver.
If you wanna know about the architecture of channels in go, you can watch this talk of gophercon-2017. I found this talk very helpful.
I have read through CommonMistakes as well as run my code through the -race flag, but I can't seem to pinpoint what is wrong here:
package main
import (
"fmt"
)
func main() {
i := 1
totalHashFields := 6
for i <= totalHashFields {
Combinations(totalHashFields, i, func(c []int) {
fmt.Println("Outside goroutine:", c)
go func(c []int) {
fmt.Println("Inside goroutine:", c)
}(c)
})
i++
}
}
func Combinations(n, m int, emit func([]int)) {
s := make([]int, m)
last := m - 1
var rc func(int, int)
rc = func(i, next int) {
for j := next; j < n; j++ {
s[i] = j
if i == last {
emit(s)
} else {
rc(i+1, j+1)
}
}
return
}
rc(0, 0)
}
(The Combinations function is a combinations algo for those interested)
Here is some of the output from fmt.Println:
Outside goroutine: [0 1 4]
Inside goroutine: [5 5 5]
Outside goroutine: [0 1 2 3 4 5]
Inside goroutine: [5 5 5 5 5 5]
Basically, even though I'm passing c as a parameter to my anonymous go function, the value is consistently different to the value outside of this scope. In the output above, I expected the 2 "Inside" values to also be [0 1 4] and [0 1 2 3 4 5], respectfully.
The problem is that you goroutines all work on distinc int slices but these share a common backing array: After completing Combinations the slice s will be full of 5s. Your c in main shares the underlying backing array with s.
But your goroutines do not start executing until Combinations is done so once they do start, the will see the final value of s which is just 5s.
Here it does not help to pass in the slice like you did as this makes a proper copy of c but not of the backing array.
Try
Combinations(totalHashFields, i, func(c []int) {
fmt.Println("Outside goroutine:", c)
cpy := make([]int, len(c))
copy(cpy, c)
go func(c []int) {
fmt.Println("Inside goroutine:", c)
}(cpy)
})
to make a "deep copy" of c.
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]
}
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]