Golang slice append exception - go

This is a leet code problem, and when I try to answer with the code blew:
package main
import "fmt"
func main() {
nums := []int{9, 0, 3, 5, 7}
fmt.Println(subsets(nums))
}
func subsets(nums []int) [][]int {
var result [][]int
result = append(result, []int{})
for _, v := range(nums) {
for _, rv := range(result) {
result = append(result, append(rv, v))
}
}
return result
}
Leetcode told me wrong answer:
Wrong Answer
Details
Input
[9,0,3,5,7]
Output
[[],[9],[0],[9,0],[3],[9,3],[0,3],[9,0,3],[5],[9,5],[0,5],[9,0,5],[3,5],[9,3,5],[0,3,5],[9,0,3,7],[7],[9,7],[0,7],[9,0,7],[3,7],[9,3,7],[0,3,7],[9,0,3,7],[5,7],[9,5,7],[0,5,7],[9,0,5,7],[3,5,7],[9,3,5,7],[0,3,5,7],[9,0,3,7,7]]
Expected
[[],[9],[0],[0,9],[3],[3,9],[0,3],[0,3,9],[5],[5,9],[0,5],[0,5,9],[3,5],[3,5,9],[0,3,5],[0,3,5,9],[7],[7,9],[0,7],[0,7,9],[3,7],[3,7,9],[0,3,7],[0,3,7,9],[5,7],[5,7,9],[0,5,7],[0,5,7,9],[3,5,7],[3,5,7,9],[0,3,5,7],[0,3,5,7,9]]
The output slice index 15, it should be [9,0,3,5] like the expected, but the result is [9,0,3,7].
So I try to run this code by go playgroud online,the answer is the same wrong, and then I run this code in goland with debug mode,I find when I make the slice append([9,0,3], 7), the output slice index 15 change at the same time.
My local go env: go version go1.17.6 windows/amd64
I'm just a beginner to golang, could anyone explain this situation?
Thank you very much.
ps: I try to use blew code to recover same issue, but I failed.
package main
import "fmt"
func main() {
a := [][]int{{}, {9}, {0}, {9, 0}, {3}, {9, 3}, {0, 3}, {9, 0, 3}, {5}, {9, 5}, {0, 5}, {9, 0, 5}, {3, 5}, {9, 3, 5}, {0, 3, 5}, {9, 0, 3, 5}}
i := 7
for _, v := range a {
// fmt.Println(a)
a = append(a, append(v, i))
// fmt.Println(a)
}
fmt.Println(a)
}
result:
[[] [9] [0] [9 0] [3] [9 3] [0 3] [9 0 3] [5] [9 5] [0 5] [9 0 5] [3 5] [9 3 5] [0 3 5] [9 0 3 5] [7] [9 7] [0 7] [9 0 7] [3 7] [9 3 7] [0 3 7] [9 0 3 7] [5 7] [9 5 7] [0 5 7] [9 0 5 7] [3 5 7] [9 3 5 7] [0 3 5 7] [9 0 3 5 7]]

You are reusing the same backing array in some of your slices, because that's what append does if there's capacity remaining. A simple fix is to replace append(rv, v) with append(append([]int{}, rv...), v), creating an entirely new slice. An alternative is to force the append to allocate a fresh backing array by capping the slice to its current length: append(rv[:len(rv):len(rv)], v).
Playground link with working code: https://go.dev/play/p/Gc-yF5KQOAO

Related

Generate all combinations of slice - design of experiment in Go

I have the following levels in a design of experiment.
levels := []int{0, 5, 10} // three levels
The factors are as follows:
factors := []int{6, 21, 7, 8, 32} // five factors
The important thing is that there are Nf factors. Number of experiments is therefore:
n := math.Pow(float64(3), float64(Nf)) // = 243
I need to generate all possible 243 combos as follows:
1: {0, 0, 0, 0, 0}
2: {0, 0, 0, 0, 5}
3: {0, 0, 0, 0, 10}
4: {0, 0, 0, 5, 0}
5: {0, 0, 0, 5, 5}
6: {0, 0, 0, 5, 10}
7: {0, 0, 0, 10, 0}
...
243: {10, 10, 10, 10, 10}
How do I go about doing this in a generic function in Go, knowing that the number of factors can be variable?
I have a solution (Cartesian product) that works, using the Gonum package.
Here below the code:
import (
"fmt"
"gonum.org/v1/gonum/stat/combin"
)
factors := []int{3, 3, 3, 3, 3} // three levels for each factor.
list := combin.Cartesian(factors)
for i, v := range list {
fmt.Println(i, v)
}
which returns the index for each level:
0 [0 0 0 0 0]
1 [0 0 0 0 1]
...
240 [2 2 2 2 0]
241 [2 2 2 2 1]
242 [2 2 2 2 2]
So if someone has a better way of doing this using the standard lib, please let me know.

When the slice element is removed, the original slice is broken

package main
import (
"fmt"
)
func main() {
// test data
var a = [][]int{
[]int{1,2},
[]int{3,4},
[]int{5,6},
[]int{7,8},
}
for i := range a {
fmt.Println(a) // print out
_ = append(a[:i], a[i+1:]...) // remove element
}
}
expected result
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
[[1 2] [3 4] [5 6] [7 8]]
actual result
[[1 2] [3 4] [5 6] [7 8]]
[[3 4] [5 6] [7 8] [7 8]]
[[3 4] [7 8] [7 8] [7 8]]
[[3 4] [7 8] [7 8] [7 8]]
https://play.golang.org/p/KahcX1MmDHO
why does this result? the original slice is broken. :(
When you re-slice you don't change the underlying array. So the first time through your loop (append(a[:0], a[1:]...)) you create a[:0] which is a slice of len 0 (cap 4) pointing to the element 0 and a[1:] is a slice of len 3 (cap 3) pointing to element 1.
As #icza pointed out using append() in this way just moved the underlying array elements around. For each loop iteration this happens:
0: elements 1-3 are moved to places 0-2
1: elements 2-3 are moved to places 1-2
2: element 3 is moved to place 2
3: nothing is moved since a[4:] has zero length
This gives the changed values that you see.
BTW Please post the simplest code which shows the problem. The nested slice is irrelevant.
func main() {
var a = []int{1,2,3,4}
for i := range a {
fmt.Println(a)
_ = append(a[:i], a[i+1:]...)
}
}

Golang - How to remove a row from a matrix?

So I have this 2D slice, for example:
s := [][]int{
{0, 1, 2, 3},
{4, 5, 6, 7},
{8, 9, 10, 11},
}
fmt.Println(s)
//Outputs: [[0 1 2 3] [4 5 6 7] [8 9 10 11]]
How can I remove a full row from this 2D slice, so that the result would look like this if I decide to remove the middle row:
[[0 1 2 3] [8 9 10 11]]
The formula to delete row at index i is:
s = append(s[:i], s[i+1:])
Here's a working example:
package main
import (
"fmt"
)
func main() {
s := [][]int{
{0, 1, 2, 3},
{4, 5, 6, 7}, // This will be removed.
{8, 9, 10, 11},
}
// Delete row at index 1 without modifying original slice by
// appending to a new slice.
s2 := append([][]int{}, append(s[:1], s[2:]...)...)
fmt.Println(s2)
// Delete row at index 1. Original slice is modified.
s = append(s[:1], s[2:]...)
fmt.Println(s)
}
Try it in the Go playground.
I recommend you to read Go Slice Tricks. Some of the tricks can be applied to multidimensional slices as well.
You can try the following:
i := 1
s = append(s[:i],s[i+1:]...)
You can try the working code in the Golang playground
Another alternative way is to use the following:
i := 1
s = s[:i+copy(s[i:], s[i+1:])]
Golang Playground

How to separate numbers from a slice?

Let's say I have a list with 10 numbers:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
I would like my program to slice every 3 numbers, for example:
[1,2,3]
[4,5,6]
[7,8,9]
How can I do it?
Grateful
For example, with n = 3,
package main
import "fmt"
func main() {
list := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
for a, n := list, 3; len(a) >= n; a = a[n:] {
slice := a[:n]
fmt.Println(slice)
}
}
Output:
[1 2 3]
[4 5 6]
[7 8 9]
you could make a something like this (sorry for pseudo code)
array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
while (array){
list = ""
for($i=1;$i -le 3;$i++){
list.add = array[$i]
remove from array the array[$i]
}
your list now here (list)
}
you could ask the first 3 values and after that you remove it

Numpy sorting help

In Numpy, how do I create an array of indices which can be used return the values of the source array in sorted order? eg:
Source:
[[4 2 6 7]
[1 4 8 9]
[3 1 0 3]]
Indices:
[10 4 9 1 8 11 0 5 2 3 6 7]
Take a look at numpy.argsort - it will return the indices that would sort your array. You can also specifiy the axis along which to sort. Try:
a = numpy.asarray([[4, 2, 6, 7], [1, 4, 8, 9], [3, 1, 0, 3]])
numpy.argsort(a.flat)
>> array([10, 4, 9, 1, 8, 11, 0, 5, 2, 3, 6, 7])
The answer's in the manual:
src = [[ ... ]]
ravel_src = np.ravel(src)
indices = np.argsort(ra)

Resources