Related
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
This question already has answers here:
Why does append() modify the provided slice? (See example)
(1 answer)
Golang append changing append parameter [duplicate]
(2 answers)
Why does append modify passed slice
(5 answers)
Deleting element of slice modifies original value [duplicate]
(1 answer)
Closed last year.
package main
import "fmt"
func main() {
src := []int{0, 1, 2, 3, 4, 5, 6}
a := src[:3]
b := src[3:]
a = append(a, 9)
fmt.Println(a, b)
}
output:
[0 1 2 9] [9 4 5 6]
Did append modified the underlay array as []int{0, 1, 2, 9, 4, 5, 6}?
Slice a was copied as a new slice with a new underlay array with value [0, 1, 2, 9] and slice b still pointing to the old array that was modified.
Thanks for any hints, much appreciated
Slice a was copied as a new slice with a new underlay array with value [0, 1, 2, 9] and slice b still pointing to the old array that was modified.
a := src[:3] created a slice (a pointer to the src head, length=3, capacity=7)
b := src[3:] created a slice(a pointer to the src[3],length=4, capacity=4)
a and b shares the same memory created by src
a = append(a, 9),when appending to the same slice, as long as it does not exceed cap, it is the same array that is modified
Did append modified the underlay array as []int{0, 1, 2, 9, 4, 5, 6}
YES
If the append exceed the cap of a, new array will be allocated and data will be copied the the new array
try this out:
package main
import "fmt"
func main() {
src := []int{0, 1, 2, 3, 4, 5, 6}
a := src[:3]
b := src[3:]
a = append(a, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9)
fmt.Println(a, b)
}
Output:
[0 1 2 9 9 9 9 9 9 9 9 9 9] [3 4 5 6]
I am looking for a way to concisely and efficiently concatenate 3 or more slices in Go.
Let's say I want to concatenate the following slices (all the code can be found here - https://play.golang.org/p/6682YiFF8qG):
a := []int{1, 2, 3}
b := []int{4, 5, 6}
c := []int{7, 8, 9}
My first attempt is by using the append method:
d1 := append(a, b...)
d1 = append(d1, c...) // [1 2 3 4 5 6 7 8 9]
However, this method is verbose and requires 2 append calls for concatenating three slices. So, for n slices, I will need n-1 calls to append, which is not only verbose, but also inefficient as it requires multiple allocations.
My next attempt is to create a variadic function to handle the concatenation with only one new slice allocation:
func concat(slicesOfSlices ...[]int) []int {
var totalLengthOfSlices int
for _, slice := range slicesOfSlices {
totalLengthOfSlices += len(slice)
}
arr := make([]int, 0, totalLengthOfSlices)
for _, slice := range slicesOfSlices {
arr = append(arr, slice...)
}
return arr
}
Then I can use it as follows:
d2 := concat(a, b, c) // [1 2 3 4 5 6 7 8 9]
To illustrate, I want to emulate the following convenient functionality of the spread operator in JavaScript, which I often use in the following way:
const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [7, 8, 9];
const d = [...a, ...b, ...c]; // [1, 2, 3, 4, 5, 6, 7, 8, 9]
In other words, I am looking for a way to do something like d3 := append(a, b, c) or d3 := append(a, b..., c...) but with the standard Go library or using less code than I did.
Note on possible duplicates
I don't think this is a duplicate of the question "How to concatenate two slices" as my question is about concatenating 3 or more slices in the most concise and idiomatic way.
You could use your first method of using append like this:
a := []int{1, 2, 3, 4}
b := []int{9, 8, 7, 6}
c := []int{5, 4, 3, 2}
a = append(a, append(b, c...)...)
That being said, I think that your variadic concat function is cleaner and isn't very much code for a utility function.
(Go Playground Link)
Good luck!
I am modifying the perimeter values on a matrix, then trying to recurse into the inner values. I expected I'd be able to access the inner values with something like matrix[1:3][1:3]. This is not the case, and I'm a bit lost as to the underlying logic of how Go handles sequential brackets.
package main
import (
"fmt"
)
var m = [][]int{
[]int{0, 1, 2, 3},
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
[]int{12, 13, 14, 15},
}
I am trying to access the values 5, 6, 9, 10 in the above matrix -- the "inner" matrix.
func main() {
inner := m[1:3][1:3]
fmt.Printf("%#v\n", inner)
// Expected Output: [][]int{
// []int{5, 6},
// []int{9, 10}
// }
// Actual Ouput: [][]int{
// []int{8, 9, 10, 11},
// []int{12, 13, 14, 15}
// }
inner = m[1:3]
fmt.Printf("%#v\n", inner)
// Output:
// [][]int{
// []int{4, 5, 6, 7},
// []int{8, 9, 10, 11}
// }
inner = innerMatrix(m)
fmt.Printf("%#v\n", inner)
// [][]int{
// []int{5, 6},
// []int{9, 10}
}
func innerMatrix(m [][]int) (inner [][]int) {
innerRows := m[1:3]
for _, row := range innerRows {
inner = append(inner, row[1:3])
}
return
}
The function innerMatrix is able to produce the output I expected. I'm lost as to why (1) m[1:3][1:3] doesn't have the same effect, (2) it seems to translate to m[2:4]. What's going on?
Playground
When you create a sub-slice in Go, you're allowed to grow that sub-slice back to the capacity of the original slice again, e.g.:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5}
b := a[1:3]
fmt.Printf("a[1:3]: %v\n", b)
c := b[1:3]
fmt.Printf("b[1:3]: %v\n", c)
}
which outputs:
a[1:3]: [2 3]
b[1:3]: [3 4]
Note that b only has two elements, but we're allowed to create a slice of the second and third elements because the capacity of the slice it's a sub-slice of is sufficiently large, and all the slices share the same underlying array. See the last example in section "Slice internals" on this page
So what's happening in your case is that m[1:3] is equivalent to:
var m1 = [][]int{
[]int{4, 5, 6, 7}, // second element of m
[]int{8, 9, 10, 11}, // third element of m
}
and m[1:3][1:3] is therefore equivalent to m1[1:3], which is equivalent to:
var m2 = [][]int{
[]int{8, 9, 10, 11}, // second element of m1
[]int{12, 13, 14, 15}, // "third" element of m1
}
with the "third" element appearing only because the capacity of m is large enough to contain it, and does in fact contain it. If m only had three elements, this would cause a panic.
In other words, m[1:3][1:3] is here exactly equivalent to m[2:4], because m[1:3][1:3] gives you the second and third elements of m[1:3]. Maybe easier to understand with a diagram:
m : []int{1, 2, 3, 4}
m[1:3] : []int{ 2, 3 }
m[1:3][1:3] : []int{ 3, 4}
m[2:4] : []int{ 3, 4}
As an oversimplification, you can imagine that the square brackets give the requested elements of whatever is immediately to the left of them, so a somewhat extreme example:
package main
import "fmt"
func main() {
a := []int{1, 2, 3, 4, 5}
b := a[1:5]
fmt.Printf("b: %v, a[1:5] : %v\n",
b, a[1:5])
c := b[1:4]
fmt.Printf("c: %v , a[1:5][1:4] : %v\n",
c, a[1:5][1:4])
d := c[1:3]
fmt.Printf("d: %v , a[1:5][1:4][1:3] : %v\n",
d, a[1:5][1:4][1:3])
e := d[1:2]
fmt.Printf("e: %v , a[1:5][1:4][1:3][1:2]: %v\n",
e, a[1:5][1:4][1:3][1:2])
}
which outputs:
b: [2 3 4 5], a[1:5] : [2 3 4 5]
c: [3 4 5] , a[1:5][1:4] : [3 4 5]
d: [4 5] , a[1:5][1:4][1:3] : [4 5]
e: [5] , a[1:5][1:4][1:3][1:2]: [5]
Here is your data:
var m = [][]int{
[]int{0, 1, 2, 3},
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
[]int{12, 13, 14, 15},
}
First you ask what is inner := m[1:3][1:3]?
Well, taking one at a time, m[1:3] is the subslice you get when grabbing elements 1 to 3 not including 3. So that is elements 1 and 2. Element 0 is []int{0, 1, 2, 3}, element 1 is []int{4, 5, 6, 7}, and element 2 is []int{8, 9, 10, 11},
So m[1:3] is
[][]int{
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
}
Now, to get m[1:3][1:3] we repeat the same thing on this result.
However, this time, there are only two elements. We again want elements 1 and 2. We skip element 0 which is []int{4, 5, 6, 7}. Element 1 is []int{8, 9, 10, 11}. There is no element 2. However, the result of m[1:3] was a subslice and the underlying slice had an additional element.
So by extending this subslice we can get that element back again, and that is the hiddent element 2 which is []int{12, 13, 14, 15}.
So m[1:3][1:3] is
[][]int{
[]int{8, 9, 10, 11},
[[]int{12, 13, 14, 15},
}
Finally, you wonder why func innerMatrix works differently? It starts by producing m[1:3] which is
[][]int{
[]int{4, 5, 6, 7},
[]int{8, 9, 10, 11},
}
Then the code IS NOT taking another subslice in the same way that m[1:3][1:3] is two consecutive subslices. Instead, you take each element in the slice and grab the subslice from each element. The first time through you grab subslices [1:3] from []int{4, 5, 6, 7}. The result of that is
[]int{5, 6}
The second time through you do the same on the second element []int{8, 9, 10, 11} which is
[]int{9, 10}
Finally, each time through you append the result to the result slice, so you append []int{5, 6} to [], to give [][]{int{5, 6}}, and then you append []int{9, 10} to give
[][]{int{5, 6}, []int{9, 10} }
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