チンチラのフンみたいなもの

毎日の学んだことを書いていきます

競プロ典型90問 004 - Cross Sum(★2)

はじめに

 転職活動で溜まったストレスを発散するため、疲れた時はちょこちょここういうの解いていきます。自分で考えて解いた後、他の人の良い書き方を見つけたら随時記事は更新していきます。最初の自分の提出についてはずっと残しときます。

問題文

H 行 W 列のマス目があります。上から i (1≤i≤H) 行目、左から j (1≤j≤W) 列目にあるマス (i,j) には、整数 A i,jが書かれています。 すべてのマス (i,j) (1≤i≤H,1≤j≤W) について、以下の値を求めてください。
 ・マス (i,j) と同じ行または同じ列にあるマス(自分自身を含む)に書かれている整数をすべて合計した値

制約

  • 2≤H,W≤2000
  • 1≤Ai,j ≤99
  • 入力は全て整数

私のコード

そのマスから縦横足した数から、そのマスの値を引いた数が求められている数であることに注目した。縦の合計や横の合計はマス間で共通するものがあるので変数に格納し、最後にそれを使ってマスの値を変更し、出力!

let ab = readLine()!.split(separator: " ").map{Int($0)!}
var twoArray:[[Int]] = []
var hSum:[Int] = []
var vSum:[Int] = []
func printResult(){
    for _ in 1 ... ab[0] {
        twoArray.append(readLine()!.split(separator: " ").map{Int($0)!})
    }
    for i in 0 ... ab[0]-1{
        hSum.append(twoArray[i].reduce(0,+))
    }
    for i in 0 ... ab[1]-1{
        var element = 0
        for j in 0 ... ab[0]-1{
            element += twoArray[j][i]
        }
        vSum.append(element)
    }
    for i in 0 ... ab[0]-1{
        for j in 0 ... ab[1]-1{
            twoArray[i][j] = hSum[i] + vSum[j] - twoArray[i][j]
        }
    }
    
    for i in 0 ... ab[0]-1{
        print(twoArray[i].map{String($0)}.joined(separator: " "))
    }
}

printResult()

他の人のコード

let s = readLine()!.split(separator: " ").map({Int(String($0))!})
let(h,w)=(s[0],s[1])
var t=[[Int]]()
var hs=[Int](repeating:0,count:h)
var ws=[Int](repeating:0,count:w)

for _ in 1...h {
    let s=readLine()!.split(separator: " ").map({Int(String($0))!})
    t.append(s)
}

for i in 0..<h {
    for j in 0..<w {
        let tij=t[i][j]
        hs[i]&+=tij
        ws[j]&+=tij
    }
}
for i in 0..<h {
    var ansl=[String]()
    for j in 0..<w {ansl.append(String(hs[i]&+ws[j]&-t[i][j]))}
    print(ansl.joined(separator: " "))
}

改善点

  • let(h,w)=(s[0],s[1]) でいちいちs[0]とか書かない
  • ..< を使えば-1いらない
  • 繰り返し使わないなら関数宣言しない
  • [Int] (repeating:,count:)で配列を作ることで、t[i][j]に合わせてiやjを指定できる
  • iが横、jが縦を表しているのだからそれに合わせて横の合計、縦の合計も作れる
  • 式が一つの時はfor文でも1行で書ける

解説