swift - 这个矩阵相邻单元格计数的解决方案有什么问题? ( swift )

标签 swift algorithm matrix

我被要求在 Swift Playground 中解决这个问题。有人告诉我我的答案是正确的,但还不够好(是的,非常模糊)。

/*

 Write a Swift playground that takes an n x n grid of integers. Each integer can be either 1 or 0.

 The playground then outputs an n x n grid where each block indicates the number of 1's around that block, (excluding the block itself) . For Block 0 on row 0, surrounding blocks are (0,1) (1,0) and (1,1). Similary for block (1,1) all the blocks around it are to be counted as surrounding blocks.

 Requirements:

 Make sure your solution works for any size grid.
 Spend an hour and a half coding the logic and another hour cleaning your code (adding comments,  cleaning variable and function names).

 Optimize your functions to be O(n^2).

 Your output lines should not have any trailing or leading whitespaces.

 Please use hard coded example input constants below.

 Examples:

 Input Grid:

 let sampleGrid = [[0,1,0], [0,0,0], [1,0,0]]

 Console Output:

 1 0 1
 2 2 1
 0 1 0

 /////////////////

 Input Grid:

 let sampleGrid = [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]

 Console Output:

 1 0 2 1
 2 2 3 1
 1 2 4 2
 2 1 3 1

 */

/// An *Error* type
struct ComputationError : Error {
    /// The message of the error
    let message : String
}

/// This function computes a matrix result from the input *matrix*
/// where an integer value represents the number of adjacent cells
/// in the input *matrix* having a 1.
///
/// The algorithm is O(n^2), if n is the side length of the matrix:
///
///  for each row in rows of matrix
///   for each column in columns of matrix
///    for each matrix[row][column] cell if equal to 1
///     add a 1 to adjacent (valid) cell in result matrix
///
/// - Parameter matrix: input square matrix with values of 0 or 1 only
/// - Returns: a matrix of equal size to input matrix with computed adjacency values
/// - Throws: throws a ComputationError is the matrix is of invalid size or has invalid values (something other than 1 or 0)
func compute(matrix:[[Int]]) throws -> [[Int]] {

    // The number of rows in matrix, which should equal the number of columns, ie side length, or n
    let side = matrix.count

    // The resulting matrix to return
    var result:[[Int]] = []

    // Initialize the result matrix
    for _ in 0..<side {
        result.append(Array<Int>(repeating: 0, count: side))
    }

    // A convenience constant to refer to the last element in a row or column
    let last = side-1

    // Iterate over rows in matrix
    for row in 0..<side {
        if matrix[row].count < side {
            throw ComputationError(message:"Invalid number of columns (\(matrix[row].count)), should match number of rows (\(side))")
        }
        // Iterate over columns in matrix
        for column in 0..<side {
            // Consider this cell if it is 1, otherwise skip
            // If it is 1, then add a 1 to all valid adjacent cells
            // in result matrix.
            if matrix[row][column] == 1 {
                if 0 < row {
                    if 0 < column {
                        result[row-1][column-1] += 1
                    }
                    result[row-1][column] += 1
                    if column < last {
                        result[row-1][column+1] += 1
                    }
                }
                if 0 < column {
                    result[row][column-1] += 1
                }
                if column < last {
                    result[row][column+1] += 1
                }
                if row < last {
                    if 0 < column {
                        result[row+1][column-1] += 1
                    }
                    result[row+1][column] += 1
                    if column < last {
                        result[row+1][column+1] += 1
                    }
                }
            }
            else if matrix[row][column] == 0 {
                // ok
            }
                // If value is neither 0 or 1 throw an error
            else {
                throw ComputationError(message:"Invalid value (\(matrix[row][column])) encountered at row \(row) and column \(column)")
            }
        }
    }

    return result
}

/// Print *matrix* to console by iterating over each row in the
/// matrix and each column in the row, regardless of the count
/// of columns in the row.  The output is row-wise and a single
/// space delimits columns, with no leading or trailing whitespace.
///
/// - Parameter matrix: an array of array of Int
func print(matrix:[[Int]]) {

    let rows = matrix.count

    for row in 0..<rows {
        let columns = matrix[row].count
        var line = ""
        for column in 0..<columns {
            if 0 < column {
                line += " "
            }
            line += "\(matrix[row][column])"
        }
        print(line)
    }

}

do {
    print(matrix:try compute(matrix: [[0,1,0], [0,0,0], [1,0,0]]))
}
catch let error {
    print(error)
}

do {
    print()
    print(matrix:try compute(matrix: [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]))
}
catch let error {
    print(error)
}

// test for exception
do {
    print()
    print(matrix:try compute(matrix: [[0,1], [0,0,0], [1,0,0]]))
}
catch let error {
    print(error)
}

// test for exception
do {
    print()
    print(matrix:try compute(matrix: [[0,1,0], [3,0,0], [1,0,0]]))
}
catch let error {
    print(error)
}

最佳答案

他们可能正在寻找函数式编程风格的东西,而您可能需要证明您的解决方案是 O(n^2)。

例如:

 // let sampleGrid = [[0,1,0], [0,0,0], [1,0,0]]
 let sampleGrid = [[0,1,0,0], [0,0,0,1], [1,0,0,1],[0,1,0,1]]

 func printMatrix(_ m:[[Any]])
 {
    print( m.map{ $0.map{"\($0)"}.joined(separator:" ")}.joined(separator:"\n") )
 }

 let emptyLine  = [Array(repeating:0, count:sampleGrid.first!.count)]

 let left  = sampleGrid.map{ [0] + $0.dropLast()  }   // O(n)
 let right = sampleGrid.map{ $0.dropFirst() + [0] }   // O(n)
 let up    = emptyLine + sampleGrid.dropLast()        // O(n)
 let down  = sampleGrid.dropFirst() + emptyLine       // O(n)

 let leftRight   = zip(left,right).map{zip($0,$1).map{$0+$1}} // O(n^2)
 let upDown      = zip(up,down).map{zip($0,$1).map{$0+$1}}    // O(n^2)

 let cornersUp   = emptyLine + leftRight.dropLast()   // O(n)
 let cornersDown = leftRight.dropFirst() + emptyLine  // O(n)

 let sides   = zip(leftRight,upDown).map{zip($0,$1).map{$0+$1}}      // O(n^2)
 let corners = zip(cornersUp,cornersDown).map{zip($0,$1).map{$0+$1}} // O(n^2)

 // 6 x O(n) + 5 x O(n^2) ==> O(n^2)
 let neighbourCounts = zip(sides,corners).map{zip($0,$1).map{$0+$1}}  // O(n^2) 

 print("SampleGrid:")
 printMatrix(sampleGrid)
 print("\nNeighbour counts:")
 printMatrix(neighbourCounts)

...

SampleGrid:
0 1 0 0
0 0 0 1
1 0 0 1
0 1 0 1

Neighbour counts:
1 0 2 1
2 2 3 1
1 2 4 2
2 1 3 1

关于swift - 这个矩阵相邻单元格计数的解决方案有什么问题? ( swift ),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45849208/

相关文章:

OpenGL:基向量如何在内存中布局

c++ - 旋转 4x4 矩阵会导致随时间缩放

swift - 如何在 ios 图表中快速设置字符串和 Y 轴数字

ios - 如何在单元格中单击按钮时获取 TableView 单元格中的标签值

algorithm - gzip 文件如何存储在 HDFS 中

c - 前N个素数优化

java - java中矩阵的对角线值相乘

ios - CoreLocation 为空,应用程序在启动时崩溃

ios - 左对齐 UICollectionView

java - 用 Java 实现调度算法