问题描述
这里有点奇怪。我的问题是,像我一样,人们运行代码的结果是否相同?如果你这样做,是我的代码(我通常是一个python程序员)或者golang中的错误吗?$ b 系统信息: Go版本(1.1.2)linux x64(fedora 19)
代码背景信息:我正在做的是找到从三角形顶部到底部的最高成本路线,这是从project_euler 18和67
错误:我设置了一个名为pathA的变量,这是一个整数列表,加上一个新的int,用于从三角形
找到的新值3,7,2追加8应该等于3,2,7,8
,它的确如此! ...直到我设置路径B. pathB被正确设置,但突然pathA与pathB的值相同。
$ b tl; dr 当我设置另一个变量时, p>
我的代码如下:
包主
import(
fmt
)
func extendPaths(triangle,prePaths [] [] int)[] [] int {
nextLine:= (##### nextLine:,nextLine)
postPaths:= [] [] int {{}}
for i:= 0;我< LEN(prePaths); i ++ {
route:= prePaths [i]
nextA:= nextLine [i]
nextB:= nextLine [i + 1]
fmt.Println(下一个A:,nextA,Next B:,nextB,\\\
)
pathA:= append(route,nextA)
fmt.Println(pathA check#1:, pathA)
pathB:= append(route,nextB)
fmt.Println(pathA check#2:,pathA,\\\
)
postPaths = append (postPaths,pathA)
postPaths = append(postPaths,pathB)
}
postPaths = postPaths [1:]
prePaths = [] [] int {postPaths [0]}
for i:= 1;我< LEN(postPaths)-1; i + = 2 {
if getSum(postPaths [i])> getSum(postPaths [i + 1]){
prePaths = append(prePaths,postPaths [i])
} else {
prePaths = append(prePaths,postPaths [i + 1])
prePaths = append(prePaths,postPaths [len(postPaths)-1])$ b $ b return prePaths
}
func getSum (sumList [] int)int {
total:= 0
for i:= 0;我< LEN(sumList); i ++ {
total + = sumList [i]
}
返回总数
}
func getPaths(triangle [] [] int){
prePaths:= [] [] int {{triangle [0] [0]}}
for i:= 0;我< LEN(三角形)-1; i ++ {
prePaths = extendPaths(triangle,prePaths)
}
}
func main(){
triangle:= [] [] int { {3},{7,4},{2,4,6},{8,5,9,3}}
getPaths(三角形)
}
$ c $
<$>
$ b 这给出了终端中的输出: c $ c> ##### PrePaths:[[3]]
##### nextLine:[7 4]
下一个A:7下一个B:4
pathA检查#1:[3 7]
pathA检查#2:[3 7]
##### PrePaths:[[3 7] [3 4]]
##### nextLine:[2 4 6]
下一个A:2下一个B:4
pathA check#1:[3 7 2]
pathA check #2:[3 7 2]
下一个A:4下一个B:6
pathA支票#1:[3 4 4]
pathA支票#2 :[3 4 4]
##### PrePaths:[[3 7 2] [3 7 4] [3 4 6]]
##### nextLine:[ 8 5 9 3]
下一个A:8下一个B:5
pathA支票#1:[3 7 2 8]
pathA支票#2:[3 7 2 5 ]
下一个A:5下一个B:9
pathA check#1:[3 7 4 5]
pathA check#2:[3 7 4 9 ]
下一个A:9下一个B: 3
pathA支票#1:[3 4 6 9]
pathA支票#2:[3 4 6 3]
在这里你可以看到最后4次我设置了pathA,它最初设置正确,但是被pathB覆盖。
有没有人对此有任何想法?
编辑:
正如下面的评论所指出的那样,需要从原件制作新的切片和复制数据。这是通过 http://blog.golang.org/go-slices
func AppendInt(slice [] int,data ... int )[] int {
m:= len(slice)
n:= m + len(data)
if n> cap(slice){
newSlice:= make([] int,(n + 1)* 2)
copy(newSlice,slice)
slice = newSlice
}
slice = slice [0:n]
copy(slice [m:n],data)
return slice
}
我也改变了另一边的代码,我在那里创建了片段pathA和pathB。这改为:
for i:= 0;我< LEN(prePaths); i ++ {
$ b $ nextA:= nextLine [i]
nextB:= nextLine [i + 1]
pathA:= AppendInt(prePaths [i],nextA)
pathB:= AppendInt(prePaths [i],nextB)
postPaths = append(postPaths,pathA)
postPaths = append(postPaths,pathB)
}
EDIT2:
这段代码不起作用(pathA被覆盖):
for i:= 0;我< LEN(prePaths); i ++ {
$ b $ nextA:= nextLine [i]
nextB:= nextLine [i + 1]
pathA:= append(prePaths [i],nextA)
pathB:= append(prePaths [i],nextB)
postPaths = append(postPaths,pathA)
postPaths = append(postPaths,pathB)
}
此代码也不起作用(pathA被覆盖):
for i:= 0;我< LEN(prePaths); i ++ {
newRoute:= make([] int,len(prePaths [i]),(cap(prePaths [i])+ 1)* 2)
copy(newRoute,prePaths [i])
nextA:= nextLine [i]
nextB:= nextLine [i + 1]
pathA:= append(newRoute,nextA)
pathB:= append(newRoute,nextB)
postPaths = append(postPaths,pathA)
postPaths = append(postPaths,pathB)
}
然而,如果我将上面的两个场景混合到下面的代码中,它可以正常工作(pathA不会被覆盖):
for i:= 0;我< LEN(prePaths); i ++ {
newRoute:= make([] int,len(prePaths [i]),(cap(prePaths [i])+ 1)* 2)
copy(newRoute,prePaths [i])
nextA:= nextLine [i]
nextB:= nextLine [i + 1]
pathA:= append(newRoute,nextA)
pathB:= append(prePaths [i],nextB)
postPaths = append(postPaths,pathA)
postPaths = append(postPaths,pathB)
}
所以,我的解决方案是制作数组的副本,并让它们使用不同的数组。 p>
切片基本上是一个由三件事组成的结构:
- 指向切片中元素数组的指针
- 该数组的长度(容量)
- 实际存储在数组中的元素的数量(长度)
运行以下代码时:
附加(x,元素)
它遵循以下ng:
- 检查扩展切片是否会超出底层数组的容量。如果是这样,请分配一个较大的元素,并将现有元素复制到新数组中,并更新容量。
- 将新元素(或元素)写入数组的末尾并更新。
- 返回新的分片。
-
len(route)== cap(route)
,并且将分配一个新的后备数组,其中pathA
和pathB
具有独立的值。
-
len(route) cap(route)
,所以pathA
和pathB
最终共享相同的支持数组。数组中的最后一个元素将是nextB
,因为该操作是以秒为单位运行的。 - A pointer to an array of the elements in the slice
- The length of that array (the "capacity")
- The number of elements actually stored in the array (the "length")
- Check if extending the slice will exceed the capacity of the underlying array. If so, allocate a larger one and copy the existing elements to the new array, and update the capacity.
- Write the new element (or elements) to the end of the array and update the length.
- Return the new slice.
len(route) == cap(route)
, and a new backing array will be allocated, withpathA
andpathB
having independent values.len(route) < cap(route)
, sopathA
andpathB
end up sharing the same backing array. The last element in the array will benextB
, since that operation was run second.
在您的代码中,您具有以下内容:
pathA:= append(route,nextA)
pathB:= append(route,nextB)
现在有两种可能性:
看起来,第一种情况对于你的循环的第一次迭代是正确的,在这之后,你遇到了第二种情况。你可以通过手动为你的路径创建一个副本来避免这种情况(使用 make()
分配一个片段,然后使用 copy() code>复制旧数据)。
So bit of a weird one here. My question is, do people get the same results from running my code as I do? And if you do, is it a fault of my code (I'm a python programmer usually), or a bug in golang?
System info: Go version (1.1.2) linux x64 (fedora 19)
Background info on the code: What I'm doing is finding the highest cost route from the top of a triangle to the bottom, this is from project_euler 18 and 67
The bug: I set a variable called pathA, this is an integer list, plus a new int for the new value found from the trianglee.g. 3, 7, 2 append 8 should equal 3, 2, 7, 8and, it does! ... until I set pathB. pathB gets set correctly however suddenly pathA is the same value as pathB.
tl;dr one variable is being overwritten when I set another
My code is as follows:
package main
import (
"fmt"
)
func extendPaths(triangle, prePaths [][]int) [][]int {
nextLine := triangle[len(prePaths)]
fmt.Println("#####PrePaths: ", prePaths)
fmt.Println("#####nextLine: ", nextLine)
postPaths := [][]int{{}}
for i := 0; i < len(prePaths); i++ {
route := prePaths[i]
nextA := nextLine[i]
nextB := nextLine[i+1]
fmt.Println("Next A:", nextA, "Next B:", nextB, "\n")
pathA := append(route, nextA)
fmt.Println("pathA check#1:", pathA)
pathB := append(route, nextB)
fmt.Println("pathA check#2:", pathA, "\n")
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
postPaths = postPaths[1:]
prePaths = [][]int{postPaths[0]}
for i := 1; i < len(postPaths)-1; i += 2 {
if getSum(postPaths[i]) > getSum(postPaths[i+1]) {
prePaths = append(prePaths, postPaths[i])
} else {
prePaths = append(prePaths, postPaths[i+1])
}
}
prePaths = append(prePaths, postPaths[len(postPaths)-1])
return prePaths
}
func getSum(sumList []int) int {
total := 0
for i := 0; i < len(sumList); i++ {
total += sumList[i]
}
return total
}
func getPaths(triangle [][]int) {
prePaths := [][]int{{triangle[0][0]}}
for i := 0; i < len(triangle)-1; i++ {
prePaths = extendPaths(triangle, prePaths)
}
}
func main() {
triangle := [][]int{{3}, {7, 4}, {2, 4, 6}, {8, 5, 9, 3}}
getPaths(triangle)
}
This gives the output in my terminal shown below:
#####PrePaths: [[3]]
#####nextLine: [7 4]
Next A: 7 Next B: 4
pathA check#1: [3 7]
pathA check#2: [3 7]
#####PrePaths: [[3 7] [3 4]]
#####nextLine: [2 4 6]
Next A: 2 Next B: 4
pathA check#1: [3 7 2]
pathA check#2: [3 7 2]
Next A: 4 Next B: 6
pathA check#1: [3 4 4]
pathA check#2: [3 4 4]
#####PrePaths: [[3 7 2] [3 7 4] [3 4 6]]
#####nextLine: [8 5 9 3]
Next A: 8 Next B: 5
pathA check#1: [3 7 2 8]
pathA check#2: [3 7 2 5]
Next A: 5 Next B: 9
pathA check#1: [3 7 4 5]
pathA check#2: [3 7 4 9]
Next A: 9 Next B: 3
pathA check#1: [3 4 6 9]
pathA check#2: [3 4 6 3]
Here you can see that for the last 4 times that I set pathA, it is initially set correctly, but then gets overwritten by pathB.
Does anyone have any thoughts on this?
EDIT:
As pointed out by the comments below, what was needed was to make new slices and copy data from the originals. This was done using code from http://blog.golang.org/go-slices-usage-and-internals modified slightly:
func AppendInt(slice []int, data ...int) []int {
m := len(slice)
n := m + len(data)
if n > cap(slice) {
newSlice := make([]int, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}
I also changed the code on the other side, where I created the slices pathA and pathB. This changed to:
for i := 0; i < len(prePaths); i++ {
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := AppendInt(prePaths[i], nextA)
pathB := AppendInt(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
EDIT2:
It's quite early in the morning here, and I flat out made a mistake in my first edit, I did not fully understand your solution, after a bit of hacking I got there in the end:
This code does not work (pathA gets overwritten):
for i := 0; i < len(prePaths); i++ {
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(prePaths[i], nextA)
pathB := append(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
This code also does not work (pathA gets overwritten):
for i := 0; i < len(prePaths); i++ {
newRoute := make([]int, len(prePaths[i]), (cap(prePaths[i])+1)*2)
copy(newRoute, prePaths[i])
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(newRoute, nextA)
pathB := append(newRoute, nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
However, if I mix the 2 scenarios above into the code below, it works fine (pathA does not get overwritten):
for i := 0; i < len(prePaths); i++ {
newRoute := make([]int, len(prePaths[i]), (cap(prePaths[i])+1)*2)
copy(newRoute, prePaths[i])
nextA := nextLine[i]
nextB := nextLine[i+1]
pathA := append(newRoute, nextA)
pathB := append(prePaths[i], nextB)
postPaths = append(postPaths, pathA)
postPaths = append(postPaths, pathB)
}
So, my solution was to make a copy of the array, and have them both use different ones.
A slice is basically a structure consisting of 3 things:
When you run the following code:
append(x, element)
It does the following:
In your code, you have the following:
pathA := append(route, nextA)
pathB := append(route, nextB)
Now there are two possibilities here:
It seems that the first case is true for the first few iterations of your loop, after which you hit the second case. You could avoid this by manually making a copy for one of your paths (allocate a slice with make()
, and then use copy()
to copy the old data).
这篇关于变量被覆盖(bug?)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!