Swiftで100マス計算を実装してみた

まず、実装したソースは以下のようになりました。

let col = [1,2,3,4,5,6,7,8,9,10]
let row = [1,2,3,4,5,6,7,8,9,10]

class Answer {
    let col: [Int]
    let row: [Int]
    let ans: [[Int]]
    init(col: [Int], row: [Int], ans: [[Int]]) {
        self.col = col;
        self.row = row;
        self.ans = ans;
    }
}

func hyakumasu(_ a:((_ x: Int,_ y: Int) -> Int), _ col: [Int], _ row: [Int]) -> Answer {
    return Answer(col: col, row: row, ans: col.map { (i) -> [Int] in row.map{ (j) -> Int in a(i, j) }})
}

func showAns(_ ans: Answer) {
    let colAns = ans.ans.map{col -> String in
        col.map{ (a) -> String in ansFormat(a)}.reduce("", + )
    }
    print(ansFormat(0) + ans.col.map{(a) -> String in ansFormat(a)}.reduce("", + ))
    for (a1, a2) in Zip2Sequence(_sequence1: ans.row, _sequence2: colAns) {
        print(ansFormat(a1) + a2)
    }
}

func ansFormat(_ ans: Int) -> String {
    return spaceSeq(4 - ans.description.count) + ans.description
}
func spaceSeq(_ x:Int) -> String {
    return [String](repeating: " ", count: x).reduce("", +)
}

showAns(hyakumasu(+, col, row))
print("")
showAns(hyakumasu(*, col, row))

各処理について

計算結果を保持するためのクラスは以下のように定義しています。

class Answer {
    let col: [Int]
    let row: [Int]
    let ans: [[Int]]
    init(col: [Int], row: [Int], ans: [[Int]]) {
        self.col = col;
        self.row = row;
        self.ans = ans;
    }
}

計算は以下の処理で行なっています。

func hyakumasu(_ a:((_ x: Int,_ y: Int) -> Int), _ col: [Int], _ row: [Int]) -> Answer {
    return Answer(col: col, row: row, ans: col.map { (i) -> [Int] in row.map{ (j) -> Int in a(i, j) }})
}

[Int]型の各行と列の要素同士に対して引数で受け取った(( x: Int, y: Int) -> Int)型の関数を適用するのは以下の処理になります。(( x: Int, y: Int) -> Int)型はInt型の引数を2つ受け取りInt型を返す関数になります。

col.map { (i) -> [Int] in row.map{ (j) -> Int in a(i, j) }})

それから計算結果をAnswer型にして返しています。

計算結果の各項目について、4文字詰でフォーマットして表示するため以下の関数を定義して4文字に足りない分はスペースを詰めて表示が崩れないようにしています。

func ansFormat(_ ans: Int) -> String {
    return spaceSeq(4 - ans.description.count) + ans.description
}
func spaceSeq(_ x:Int) -> String {
    return [String](repeating: " ", count: x).reduce("", +)
}

計算結果の表示には以下の関数を使用しています。

func showAns(_ ans: Answer) {
    let colAns = ans.ans.map{col -> String in
        col.map{ (a) -> String in ansFormat(a)}.reduce("", + )
    }
    print(ansFormat(0) + ans.col.map{(a) -> String in ansFormat(a)}.reduce("", + ))
    for (a1, a2) in Zip2Sequence(_sequence1: ans.row, _sequence2: colAns) {
        print(ansFormat(a1) + a2)
    }
}

colAnsには計算結果のInt型の配列に対してフォーマットをかけて行毎で連結させて[String]にしたものをセットしています。

let colAns = ans.ans.map{col -> String in
    col.map{ (a) -> String in ansFormat(a)}.reduce("", + )
}

print(ansFormat(0) + ans.col.map{(a) -> String in ansFormat(a)}.reduce("", + )) の部分では入力行の配列にフォーマットをかけておいて先頭に0を付与したものを表示しています。

for (a1, a2) in Zip2Sequence(_sequence1: ans.row, _sequence2: colAns) {
    print(ansFormat(a1) + a2)
}

の部分では各列と列毎の計算結果をフォーマットしたものを連結して表示するようにしています。

計算をするときは以下のように適用する関数と行、列の関数を引数として渡しています。

showAns(hyakumasu(+, col, row))
print("")
showAns(hyakumasu(*, col, row))

結果として以下のように計算結果が表示されるのが確認できます。

   0   1   2   3   4   5   6   7   8   9  10
   1   2   3   4   5   6   7   8   9  10  11
   2   3   4   5   6   7   8   9  10  11  12
   3   4   5   6   7   8   9  10  11  12  13
   4   5   6   7   8   9  10  11  12  13  14
   5   6   7   8   9  10  11  12  13  14  15
   6   7   8   9  10  11  12  13  14  15  16
   7   8   9  10  11  12  13  14  15  16  17
   8   9  10  11  12  13  14  15  16  17  18
   9  10  11  12  13  14  15  16  17  18  19
  10  11  12  13  14  15  16  17  18  19  20

   0   1   2   3   4   5   6   7   8   9  10
   1   1   2   3   4   5   6   7   8   9  10
   2   2   4   6   8  10  12  14  16  18  20
   3   3   6   9  12  15  18  21  24  27  30
   4   4   8  12  16  20  24  28  32  36  40
   5   5  10  15  20  25  30  35  40  45  50
   6   6  12  18  24  30  36  42  48  54  60
   7   7  14  21  28  35  42  49  56  63  70
   8   8  16  24  32  40  48  56  64  72  80
   9   9  18  27  36  45  54  63  72  81  90
  10  10  20  30  40  50  60  70  80  90 100