首页 > 解决方案 > 在 Swift 中的网格中查找总和的更好方法

问题描述

我有一个 6x7 网格的应用程序,可以让用户输入值。获得每个值后,应用程序会检查是否有任何连续值创建了一个 10 的总和并执行进一步的代码(我在编写的 4 个测试用例中运行良好)。到目前为止,我一直在编写类似于以下的 if 语句:

func findTens() {
        if (rowOneColumnOnePlaceHolderValue + rowOneColumnTwoPlaceHolderValue) == 10 {
            //code to execute
        } else if (rowOneColumnOnePlaceHolderValue + rowOneColumnTwoPlaceHolderValue + rowOneColumnThreePlaceHolderValue) == 10 {
            //code to execute
        } else if (rowOneColumnOnePlaceHolderValue + rowOneColumnTwoPlaceHolderValue + rowOneColumnThreePlaceHolderValue + rowOneColumnFourPlaceHolderValue) == 10 {
            //code to execute
        } else if (rowOneColumnOnePlaceHolderValue + rowOneColumnTwoPlaceHolderValue + rowOneColumnThreePlaceHolderValue + rowOneColumnFourPlaceHolderValue + rowOneColumnFivePlaceHolderValue) == 10 {
            //code to execute
}

这不是第一行的一半,它最终将成为一组非常大的 if 语句(如果我计算正确,则为 231,因为单个 7 列行将是 1,2-1,2,3-.. .-2,3-2,3,4-...-67 所以每行有 21 种可能性)。我认为必须有一种更简洁的方法,但我一直在努力寻找更好的方法。

我考虑过使用类似于以下内容的每个 rowXColumnYPlaceHolderValue 变量的数组:

let rowOnePlaceHolderArray = [rowOneColumnOnePlaceHolderValue, rowOneColumnTwoPlaceHolderValue, rowOneColumnThreePlaceHolderValue, rowOneColumnFourPlaceHolderValue, rowOneColumnFivePlaceHolderValue, rowOneColumnSixPlaceHolderValue, rowOneColumnSevenPlaceHolderValue]
        for row in rowOnePlaceHolderArray {
           //compare each element of the array here, 126 comparisons 
        }

但是我正在努力寻找该方法的下一步,除了这些数组元素显然是因为复制而不是引用原始数组的事实......

我很幸运能够找到一些相当聪明的解决方案来解决我在应用程序中遇到的一些其他问题,但是这个问题已经给我带来了大约一周的麻烦,所以我想寻求帮助,看看有什么想法我可能会失踪。可能不会有另一种方法明显优于 231 if 语句方法,这没关系。先感谢您!

标签: swift

解决方案


这是一个想法(在我的脑海中;我没有费心去优化)。我假设您的目标是:

给定一个 Int 数组,找到总和为给定 Int 总数的第一个连续元素。

您使用“10”作为目标总数只是其中的一个特例。

因此,我将查找总和为给定总数的连续元素,如果找到它们,我将返回它们在原始数组中的范围。如果我没有找到,我会返回nil

开始了:

extension Array where Element == Int {
    func rangeOfSum(_ sum: Int) -> Range<Int>? {
        newstart:
        for start in 0..<count-1 {
            let slice = dropFirst(start)
            for n in 2...slice.count {
                let total = slice.prefix(n).reduce(0,+)
                if total == sum {
                    return start..<(start+n)
                }
                if total > sum {
                    continue newstart
                }
                if n == slice.count && total < sum {
                    return nil
                }
            }
        }
        return nil
    }
}

例子:

[1, 8, 6, 2, 8, 4].rangeOfSum(10) // 3..<5, i.e. 2,8
[1, 8, 1, 2, 8, 4].rangeOfSum(10) // 0..<3, i.e. 1,8,1
[1, 8, 3, 2, 9, 4].rangeOfSum(10) // nil

好的,现在我们已经知道了,从网格中提取每个可能的行或列(或者无论游戏的目的是什么)留给读者作为练习。


推荐阅读