func cross(s1 [][]uint, s2 []uint) [][]uint {
s1CrossS2 := [][]uint{}
for _, s1Elem := range s1 {
for _, s2Elem := range s2 {
if !sliceContains(s1Elem, s2Elem) {
s1ElemUpdated := append(s1Elem, s2Elem)
s1CrossS2 = append(s1CrossS2, s1ElemUpdated)
}
}
}
return s1CrossS2
}
func indexPermutations(sample []uint, k uint) [][]uint {
// If something is not possible, then it's empty. BiG bReN
if uint(len(sample)) < k {
return [][]uint{}
}
space := [][]uint{{}}
for range k {
space = cross(space, sample)
fmt.Println(space)
fmt.Println()
}
return space
}
func sliceContains[T comparable](slice []T, item T) bool {
for _, v := range slice {
if v == item {
return true
}
}
return false
}
#Why do the elements start to repeat for length >= 4?
19 messages · Page 1 of 1 (latest)
Suppose my main function is
a := []uint{1, 2, 3, 4, 5, 6, 7}
k := uint(4)
r := indexPermutations(a, k)
If I print r, every element appears 4 times. Why?
From this of code from the indexPermutations function,```go
for range k {
space = cross(space, sample)
fmt.Println(space)
fmt.Println()
}
I can see that it does start off as intended but then it starts repeating elements after length >= 4
Not sure why
I have a python version too if anyone would like to see that.
because you are writing to s1elem 4 times
slices are mutable types that share a pointer to an underlyign array
s1ElemUpdated := append(s1Elem, s2Elem)
may or may not create a new underlying array, depending on cap(s1Elem)
for instance (tho in the example I need to be more explicit to show what's going on):
a := make([]int, 2, 4) // len = 2, cap = 4
a[0] = 1
a[1] = 2
fmt.Println(a) // easy so far
fmt.Println(append(a, 10)) // a can fit 4 elements (per the cap), a[2] is now 10
fmt.Println(append(a, 20)) // a can fit 4 elements (per the cap), a[2] is now 20
fmt.Println(append(a, 30)) // a can fit 4 elements (per the cap), a[2] is now 30
fmt.Println(a[:cap(a)]) // we need to extend a's length explicitly here to see the new elements
in short:
- a slice is a
type slice struct { ptr *T; len, cap int } - append always returns a new slice
- the new slice will point to the same data so long as it has sufficient capacity to hold the new elements, otherwise a new backing array will be allocated
everything in go is passed by value, meaning everything is copied
but a pointer is "just a number", so copying it only copies the address, not what it points to
pointer types and types with inner pointers act like reference types, they are sharing data
Wow, that's newwwww.
What's the ideal way to prevent this from happening?
The one I can think of is to make an empty array with more length and then copy data but it doesn't sound ideal.
"ideal" is ill defined
if you don't want to share data the solution is to not share data :p
explicitly allocating a new slice is certainly the most straightforward option
you are doing so implicitly here: go s1CrossS2 = append(s1CrossS2, s1ElemUpdated)
I mean it sounds like it will slow down the process. Also, in case this happens again in the future, should I check the cap of the slice before appending? I've never seen anyone do this in their code though.
just append to that isnteadof s1
Do you mean I should just do
append(s1CrossS2, ...)
// Instead of
s1CrossS2 = append(...)
```?
oh I missread it, they are not the same type
Oh by the way @median horizon, thanks for telling me about this. I wouldn't have known about this without you :)
The bug has been fixed now.