Reputation: 3667
I have two Go functions:
func permutation(prefix, str []int) {
n := len(str)
if n == 0 {
fmt.Println(prefix)
} else {
for i := 0; i < n; i++ {
permutation(
append(prefix, str[i]),
append(str[0:i], str[i+1:]...),
)
}
}
}
func perms(prefix, str string) {
n := len(str)
if n == 0 {
fmt.Println(prefix)
} else {
for i := 0; i < n; i++ {
perms(
prefix+string(str[i]),
string(str[0:i])+string(str[i+1:]),
)
}
}
}
The first takes an array of ints, the second takes a string. They both then calculate all permutations of the array, or the string.
I can run them like so:
permutation([]int{}, []int{1, 2, 3})
perms("", "123")
Their output is not the same:
$ go run main.go
[1 2 3]
[1 3 3]
[3 3 3]
[3 3 3]
[3 3 3]
[3 3 3]
123
132
213
231
312
321
I guess there is some nuance to appending arrays that I am missing. I can't seem to figure it out. Any idea what's going on?
Upvotes: 1
Views: 65
Reputation: 13062
While str1+str2
does return new (unrelated in terms of memory) string, append
doesn't behave this way. For example append(str[0:i], str[i+1:]...)
will destroy original content of str
, overwriting str[i:]
with str[i+1:]
. This is because str[0:i]
will have capacity to append str[i+1:]
without allocating new buffer.
The solution would be to create a completely new array in every iteration. At least for str
, as append(prefix, str[i])
is immune to this problem. For example:
for i := 0; i < n; i++ {
var s []int
s = append(s, str[0:i]...)
s = append(s, str[i+1:]...)
permutation(append(prefix, str[i]), s)
}
https://play.golang.org/p/lXwu39AA0V
More about slices and mechanism of append:
http://blog.golang.org/go-slices-usage-and-internals
https://blog.golang.org/slices
Upvotes: 2