Confused about the depth-first-search result when using Golang - go
I tried to solve the 'Combination Sum' on leetcode, and the result is wrong when using test case:
[7,3,2] 18
I used C++ with the same logic and passed, but when using Golang, my result is:
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,7,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
and the correct one should be
[[2,2,2,2,2,2,2,2,2],[2,2,2,2,2,2,3,3],[2,2,2,2,3,7],[2,2,2,3,3,3,3],[2,2,7,7],[2,3,3,3,7],[3,3,3,3,3,3]]
the code is shown below:
import "sort"
func combinationSum(candidates []int, target int) [][]int {
result := make([][]int, 0, 0)
resultp := &result
sort.Ints(candidates)
helper(candidates, 0, target, make([]int, 0, 0), resultp, len(candidates))
return *resultp
}
func helper(nums []int, index int, target int, list []int, resultp *[][]int, length int) {
if target == 0 {
*resultp = append(*resultp, list)
return
}
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if (nums[i] > target) {
break
}
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
}
}
Can anyone tell me why the result is incorrect, I am just confused about the [2,2,2,2,2,7,3,3] in my answer, why the 7 is before the 3 since the array has been sorted? Or anyone can tell me what mistake I have made in my code
append function may or may not modify the underlying array that your slice refers to. So you are not creating a completely new list when using append. I changed helper to match your desired behavior.
for i := index; i < length; i++ {
if i != index && nums[i] == nums[i - 1] {
continue
}
if nums[i] > target {
break
}
var newList []int
newList = append(newList, list...)
newList = append(newList, nums[i])
helper(nums, i, target - nums[i], newList, resultp, length)
}
If list has capacity, then it will be modified and therefore you are modifying your argument. Instead make a copy of list, and then append nums[i] to it.
See Go Slices: usage and internals
The line
helper(nums, i, target - nums[i], append(list, nums[i]), resultp, length)
may not perform as expected. It is called within the loop, and you are probably assuming that in the each iteration the append will always add the new member to the existing slice. If has more complex behavior that you seem not caring about enough:
If the new value fits into the current capacity of the backing array withing the slice, it is added to the current backing array. All variables assigned to that slice now report the updated content with the added new value present.
If the value does not fit, a new array is allocated. In this case further modifications of the returned slice will not change the content of the initial slice if that old value is also retained.
I am under impression that you may not expect value/content disagreement between the value returned by append and the parameter list you pass to it.
This behavior is described here (scroll to "gotcha").
So you can see the behavior a bit better by adding some print output:
https://play.golang.org/p/JPmqoAJE4S
Importantly, you can see it at this point:
0694 helper [2 3 7] 1 1 [2 2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
4425 calling down 1 6 [2 2 2 2 2 2] 3
8511 helper [2 3 7] 1 3 [2 2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2]] 3
8511 calling down 1 3 [2 2 2 2 2 2 3] 3
8162 helper [2 3 7] 1 0 [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2]] 3
8162 solution [2 2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3]]
1318 calling down 1 8 [2 2 2 2 2] 3
5089 helper [2 3 7] 1 5 [2 2 2 2 2 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
5089 calling down 1 5 [2 2 2 2 2 3] 3
4728 helper [2 3 7] 1 2 [2 2 2 2 2 3 3] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 3 3 3]] 3
1318 calling down 2 8 [2 2 2 2 2] 7
3274 helper [2 3 7] 2 1 [2 2 2 2 2 7] [[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 7 3 3]] 3
This is the sequence of actions:
You recursively call with [2 2 2 2 2 2 3] and append 3. You find that this is a valid solution and add [2 2 2 2 2 2 3 3] to the result slice.
You return up a few levels until you're back to [2 2 2 2 2] (before adding the 6th 2) and start trying to add 3s. You recursively call with [2 2 2 2 2] and append 3. Unfortunately, this overwrites your existing solution [2 2 2 2 2 2 3 3]. Since it's using the same backing array, you append 3 to the first 5 items in that slice, overwriting the 6th index in the slice you previously added to your solution set. Your second solution becomes [2 2 2 2 2 3 3 3] (note the 3 in the 6th slot)
You find that this solution set isn't going to work after a couple iterations (at [2 2 2 2 2 3 3]) because the remaining target (2) is less than the last number added (3), so you return up.
You repeat this sequence with a 7 in the 6th slot, overwriting the underlying array index again. Your second solution becomes [2 2 2 2 2 7 3 3], because you're still using the same underlying array. You find this solution also won't work, and return up.
After this point, you return up to before the list slice was greater than 4 in length (which is when the slice grew, by default it grows by doubling in size), meaning you're using a different (previous) backing array, which is why further iterations do not further change the existing solutions. By luck, none of the remaining solutions collide in a similar fashion.
This alternative print version shows you where the backing array changes (by showing where the address of the first entry changes): https://play.golang.org/p/nrgtMyqwow. As you can see, it changes when you grow beyond lengths 2, 4, and 8, but as you return upwards, you end up reverting back to different backing arrays.
The easiest solution to fix your specific problem is to copy the list slice before adding it to the solution set:
if target == 0 {
sol := make([]int, len(list))
copy(sol, list)
*resultp = append(*resultp, sol)
return
}
https://play.golang.org/p/3qTKoAumj0
[[2 2 2 2 2 2 2 2 2] [2 2 2 2 2 2 3 3] [2 2 2 2 3 7] [2 2 2 3 3 3 3] [2 2 7 7] [2 3 3 3 7] [3 3 3 3 3 3]]
Related
Sortperm for matrix sorting in Julia lang
I am using Julia 1.6.1. B is a matrix. For example, B = [ 2 4 4 4 5 ; 1 2 2 3 5 ; 1 2 3 3 3 ; 1 2 2 5 6 ; 1 3 4 4 4 ; ] I wanted to sort it forcsing on each row. sortedB = sortslices( B, dims=1, rev=true) Then, we get sorted B sortedB = [ 2 4 4 4 5 ; # 1st row of the original matrix B 1 3 4 4 4 ; # 5th row of the original matrix B 1 2 3 3 3 ; # 3rd row of the original matrix B 1 2 2 5 6 ; # 4th row of the original matrix B 1 2 2 3 5 ;] # 2nd row of the original matrix B I would like to get the array [1 5 3 4 2]. How can I do that ? It seems that sortperm does not work. sortperm( sortslices( B, dims=1, rev=true) ) # ERROR: MethodError; no method matching sortperm(::Matrix{Int64})
If performance is an issue use a non-allocating version. julia> sortperm(view.(Ref(B), 1:size(B,1), :), rev=true) 5-element Vector{Int64}: 1 5 3 4 2 Here are some benchmarks using BenchmarkTools: julia> #btime sortperm(view.(Ref($B), 1:size($B,1), :),rev=true); 376.471 ns (3 allocations: 432 bytes) julia> #btime sortperm(collect(eachslice($B,dims=1)),rev=true) 642.683 ns (6 allocations: 496 bytes);
you can use eachrow or eachslice: julia> C = collect(eachslice(B,dims=1)) 5-element Vector{SubArray{Int64, 1, Matrix{Int64}, Tuple{Int64, Base.Slice{Base.OneTo{Int64}}}, true}}: [2, 4, 4, 4, 5] [1, 2, 2, 3, 5] [1, 2, 3, 3, 3] [1, 2, 2, 5, 6] [1, 3, 4, 4, 4] julia> sortperm(C,rev=true) 5-element Vector{Int64}: 1 5 3 4 2 although this will allocate more than necessary (collect is needed apparently)
re-slicing 2d slice in go
I came across a problem which needed editing several indexes of a 2-dimensional slice. Imagine the following numbers as a 2-d slice of slices a [][]int 0 1 2 3 1 2 3 4 2 3 4 5 3 4 5 6 The problem is that I want to access and modify 0 1 1 2 As a sub-slice and I want a to be changed as well. I achieved that with this code : sub := a[:2] for i := range sub { sub[i] = sub[i][:2] } Now fmt.Println(sub) prints [[0 1] [1 2]] But the problem is fmt.Println(a) is printing [[0 1] [1 2] [2 3 4 5] [3 4 5 6]] The question is, how can I access this sub-slice without losing any data?
If your goal to modify the original []int slice elements when using sub, then copy the elements of a to a new slice. The code in the question modifies a directly. sub := make([][]int, 2) for i := range sub { sub[i] = a[i][:2] }
Just found a solution but don't know if it's the right way of doing so sub := make([][]int, 2) for i := range sub { sub[i] = a[i][:2] } sub[0][0] = "876" fmt.Println(a) fmt.Println(sub) now in the output I have [[876 1 2 3] [1 2 3 4] [2 3 4 5] [3 4 5 6]] [[876 1] [1 2]]
Go concurrent worker routines using slice type input and output channels
I am relatively new to the Go language. Even though I don't hope so, I maybe bother you with a silly question. My apologies upfront, just in case... Here's my example: I defined a worker() function which is called from main() as a set of concurrent Go routines. Input and output data is provided via an input and an output channel both of slice type []int. In one case everything works as expected, in the other case the result is faulty. See the comments in the code and the program output below the code. Honestly, I don't see the actual difference between both code variants. What did I miss here? Thank you for any advice! package main import "fmt" import "runtime" func worker(x_ch <-chan []int, y_ch chan<- []int, wid int) { for x := range x_ch { y := x fmt.Println(" worker", wid, "x:", x) fmt.Println(" worker", wid, "y:", y) y_ch <- y } } func main() { n_workers := runtime.NumCPU() n_len := 4 n_jobs := 4 x := make([]int, n_len) x_ch := make(chan []int, 10) y_ch := make(chan []int, 10) for j := 0; j < n_workers; j++ { go worker(x_ch, y_ch, j) } for k := 0; k < n_jobs; k++ { // variant 1: works! x = []int{k, k, k, k} // variant 2: doesn't work! // for i := range x { x[i] = k } fmt.Println("main x:", k, x) x_ch <- x } close(x_ch) for i := 0; i < n_jobs; i++ { z := <- y_ch fmt.Println(" main y:", i, z) } } Correct output (variant 1): main x: 0 [0 0 0 0] main x: 1 [1 1 1 1] main x: 2 [2 2 2 2] main x: 3 [3 3 3 3] worker 3 x: [3 3 3 3] worker 3 y: [3 3 3 3] worker 2 x: [2 2 2 2] worker 2 y: [2 2 2 2] worker 1 x: [0 0 0 0] worker 1 y: [0 0 0 0] worker 0 x: [1 1 1 1] worker 0 y: [1 1 1 1] main y: 0 [3 3 3 3] main y: 1 [2 2 2 2] main y: 2 [0 0 0 0] main y: 3 [1 1 1 1] Wrong output (variant 2): main x: 0 [0 0 0 0] main x: 1 [1 1 1 1] main x: 2 [2 2 2 2] main x: 3 [3 3 3 3] worker 3 x: [3 3 3 3] worker 3 y: [3 3 3 3] main y: 0 [3 3 3 3] worker 0 x: [2 2 2 2] worker 0 y: [3 3 3 3] main y: 1 [3 3 3 3] worker 1 x: [1 1 1 1] worker 1 y: [3 3 3 3] main y: 2 [3 3 3 3] worker 2 x: [3 3 3 3] worker 2 y: [3 3 3 3] main y: 3 [3 3 3 3]
The difference is that in variant 1, you're sending a different slice every time, whereas in variant 2, you're sending the same slice every time (the one created above the for loops). Without creating a new slice, you're just setting the elements of the same slice to different values, so the goroutines see whatever values happen to be in the slice when they look at it. In variant 2, main will always see [3 3 3 3] because that's the final value after you've gone through the loop 4 times. The value of a slice object contains a reference to the underlying elements, not the elements themselves. There's a good explanation of slices here.
Thanks a lot for your explanation, now I see where the problem is. I added some debug code to output the pointer addresses and the result is (with slighty reformatted output): Variant 1: main 0 x=[0 0 0 0] &x=0x1830e180 &x[0]=0x1830e1e0 main 1 x=[1 1 1 1] &x=0x1830e180 &x[0]=0x1830e230 main 2 x=[2 2 2 2] &x=0x1830e180 &x[0]=0x1830e270 main 3 x=[3 3 3 3] &x=0x1830e180 &x[0]=0x1830e2a0 worker 3 x=[3 3 3 3] &x=0x1830e1d0 &x[0]=0x1830e2a0 worker 3 y=[3 3 3 3] &y=0x1830e2e0 &y[0]=0x1830e2a0 main 0 y=[3 3 3 3] &y=0x1830e2d0 &y[0]=0x1830e2a0 worker 0 x=[0 0 0 0] &x=0x1830e1a0 &x[0]=0x1830e1e0 worker 0 y=[0 0 0 0] &y=0x1830e370 &y[0]=0x1830e1e0 main 1 y=[0 0 0 0] &y=0x1830e360 &y[0]=0x1830e1e0 worker 1 x=[1 1 1 1] &x=0x1830e1b0 &x[0]=0x1830e230 worker 1 y=[1 1 1 1] &y=0x1830e400 &y[0]=0x1830e230 main 2 y=[1 1 1 1] &y=0x1830e3f0 &y[0]=0x1830e230 worker 2 x=[2 2 2 2] &x=0x1830e1c0 &x[0]=0x1830e270 worker 2 y=[2 2 2 2] &y=0x1830e480 &y[0]=0x1830e270 main 3 y=[2 2 2 2] &y=0x1830e470 &y[0]=0x1830e270 Variant 2: main 0 x=[0 0 0 0] &x=0x1830e180 &x[0]=0x1830e190 main 1 x=[1 1 1 1] &x=0x1830e180 &x[0]=0x1830e190 main 2 x=[2 2 2 2] &x=0x1830e180 &x[0]=0x1830e190 main 3 x=[3 3 3 3] &x=0x1830e180 &x[0]=0x1830e190 worker 3 x=[3 3 3 3] &x=0x1830e1d0 &x[0]=0x1830e190 worker 3 y=[3 3 3 3] &y=0x1830e2a0 &y[0]=0x1830e190 main 0 y=[3 3 3 3] &y=0x1830e290 &y[0]=0x1830e190 worker 0 x=[3 3 3 3] &x=0x1830e1a0 &x[0]=0x1830e190 worker 0 y=[3 3 3 3] &y=0x1830e330 &y[0]=0x1830e190 main 1 y=[3 3 3 3] &y=0x1830e320 &y[0]=0x1830e190 worker 1 x=[3 3 3 3] &x=0x1830e1b0 &x[0]=0x1830e190 worker 1 y=[3 3 3 3] &y=0x1830e3c0 &y[0]=0x1830e190 main 2 y=[3 3 3 3] &y=0x1830e3b0 &y[0]=0x1830e190 worker 2 x=[3 3 3 3] &x=0x1830e1c0 &x[0]=0x1830e190 worker 2 y=[3 3 3 3] &y=0x1830e440 &y[0]=0x1830e190 main 3 y=[3 3 3 3] &y=0x1830e430 &y[0]=0x1830e190
How sort this list in netlogo
I am trying to order the following list in netoglo: [[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]] Actually they are list lists and what I want is to sort by the first element of each sublist: When I use sort [[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]] It returns empty I suppose because it only sees lists and not anything so I sort. Any ideas.
Thanks to alan the answer was show sort-by [first ?1 > first ?2][[0.1 [1 2 5 3 1]] [0.3 [1 2 1 3 1]] [0.2 [1 2 1 3 1]]]
Balanced layout of n items in a grid
I have a list of n logos to display in a grid, with a maximum of 3 per row. What's an algorithm to decide how many to display per row such that the number of logos per row is as balanced as possible without using more than the minimum possible number of rows? For example: n -> number in each row 1 -> 1 2 -> 2 3 -> 3 4 -> 2, 2 5 -> 3, 2 6 -> 3, 3 7 -> 3, 2, 2 8 -> 3, 3, 2 9 -> 3, 3, 3 10 -> 3, 3, 2, 2
For N <= 3 just use N. If N is exactly divisible by 3 then use: 3 3 ... 3 If N when divided by 3 has remainder 1 then use: 3 3 ... 2 2 If N when divided by 3 has remainder 2 then use: 3 3 ... 3 2
AS confusing as your question is, I think what you need to do is first determine: number_of_rows = ceil(number_of_logos / 3.0) Then add a logo to each row, one at a time. Python: import math def partition_logos(count, lsize): num_lines = int(math.ceil(count / float(lsize))) partition = [0] * num_lines for i in xrange(count): partition[i%num_lines] += 1 return partition >>> for i in xrange(1,11): ... print partition_logos(i, 3) [1] [2] [3] [2, 2] [3, 2] [3, 3] [3, 2, 2] [3, 3, 2] [3, 3, 3] [3, 3, 2, 2]
A recursive solution, in Python: def logos_by_row(N, rows): width = 0 if N > 4 or N == 3: width = 3 elif N == 4 or N == 2: width = 2 elif N == 1: width = 1 if width != 0: rows.append(width) logos_by_row(N - width, rows) answer = [] for i in range(10): logos_by_row(i+1, answer) print answer
just use n/3 to calculate the row and n%3 to calculate the column edit: ok i saw you edited your question.... i din't saw that you want to display 2 in each row if the are 4 logos. but then you can use n mod 3 to calculate if their is a reminder as others already suggested if n%3 = 0 then just put 3 logos in each row if n%3 = 1 then put the last 4 logos in two rows if n%3 = 2 then put 3 logos in n row and the last 2 logos in a separate row