我正在努力学习Go,并尝试解决此处所解释的问题https://projecteuler.net/problem=215
我提出了一个有效的解决方案,但是一旦问题变得复杂就需要很长时间才能计算出来,在没有解决问题的情况下运行数小时,所以我认为我需要以某种方式优化我的解决方案。以下是我的代码
package main
import "fmt"
func main() {
fmt.Println(wall(18, 10))
}
func wall(width, height int) int64 {
var total int64
combinations := findCombinations(width)
combiPointer := &combinations
for i := 0; i < 4; i++ {
for _, a := range combinations[i] {
if i%2 == 0 {
buildWall(a, combiPointer[i+1], 0, height, i+1, &total, combiPointer)
} else {
buildWall(a, combiPointer[i-1], 0, height, i-1, &total, combiPointer)
}
}
}
return total
}
func buildWall(a []int, combi [][]int, level, height, index int, total *int64, pointer *[4][][]int) {
level++
var canCombine bool
for _, a1 := range combi {
canCombine = true
for _, value := range a {
if canCombine == false {
break
}
for _, value1 := range a1 {
if value == value1 {
canCombine = false
break
}
}
}
if canCombine == true && level < height {
if index%2 == 0 {
buildWall(a1, pointer[index+1], level, height, index+1, total, pointer)
} else {
buildWall(a1, pointer[index-1], level, height, index-1, total, pointer)
}
} else if level == height {
*total++
break
}
}
}
findCombinations正常工作并返回包含所有可能解决方案的三维数组。 [0]和[1]中的数组可以(可能)相互叠加而不会发生裂缝。 [2]和[3]相同。我选择通过查看用于构建墙的第一个和最后一个块的位置来切割4个阵列中的所有解决方案的数组,因为我认为它会提高性能以循环遍历较小的阵列。
func findCombinations(width int) [4][][]int {
var i int
var tmp int
var tmpInt1 int
var tmpInt2 int
open := make([][]int, 0, 100)
var solutionsHolder [4][][]int
open = append(open, []int{3, 2})
tmpArray := make([]int, 0, 100)
for {
if len(open[i]) > 0 {
tmpArray = append(tmpArray[:i], open[i][0])
open[i] = append(open[i][:0], open[i][1:]...)
counter := 0
for _, x := range tmpArray {
counter += x
}
if counter == width {
solutionArray := make([]int, len(tmpArray)-1)
counter2 := 0
for n := 0; n < len(tmpArray)-1; n++ {
if n == 0 {
tmpInt1 = tmpArray[n] % 2
}
counter2 += tmpArray[n]
solutionArray[n] = counter2
}
tmpInt2 = counter2 % 2
if tmpInt1 == 0 && tmpInt2 == 0 {
solutionsHolder[0] = append(solutionsHolder[0], solutionArray)
} else if tmpInt1 == 1 && tmpInt2 == 1 {
solutionsHolder[1] = append(solutionsHolder[1], solutionArray)
} else if tmpInt1 == 1 && tmpInt2 == 0 {
solutionsHolder[2] = append(solutionsHolder[2], solutionArray)
} else {
solutionsHolder[3] = append(solutionsHolder[3], solutionArray)
}
for _, v := range open {
tmp += len(v)
}
if tmp == 0 {
return solutionsHolder
}
tmp = 0
} else if counter > width {
for _, v := range open {
tmp += len(v)
}
if tmp == 0 {
return solutionsHolder
}
tmp = 0
} else if counter < width {
i++
if len(open) <= i {
open = append(open, []int{3, 2})
} else {
open[i] = append(open[i], []int{3, 2}...)
}
}
} else {
i--
}
}
}
它的wall函数调用一个递归函数,如果你插入一个宽度和高度的墙(32,10),它会运行很长一段时间(我已经运行了一个小时没有结果)希望你在网站上计算。
通过墙壁调用的buildWall()检查两个解决方案的相同位置是否没有裂缝,如果是这种情况,它会再次为墙壁的下一层运行buildWall,直到达到墙壁高度。它将每个解决方案与其他所有可能的解决方案进行比较,但仅限于3d阵列的一个子集。
我想也许有另一种方法可以找到所有可以组合的墙,但我似乎无法绕过它。