Swift教室 Swift と競技プログラミングの教室

競プロ Swift チートシート

読了目安 約2分

入力、配列、ソート、集計、二分探索。コピーして使う定型句集。

この章の目次

コンテスト中にコピーして使う定型句を集めました。 すべてこのサイトの本編で説明した書き方です。 思ったとおりに動かないときは、コンパイルエラー集 も合わせて見てください。

入力

Swift
// 1 行に 1 つの整数
let n = Int(readLine()!)!

// 1 行に空白区切りで複数の整数
let a = readLine()!.split(separator: " ").map { Int($0)! }

// N 行にわたって 1 整数ずつ
let values = (0..<n).map { _ in Int(readLine()!)! }

// N 行の空白区切りを 2 次元配列に
let rows = (0..<n).map { _ in readLine()!.split(separator: " ").map { Int($0)! } }

配列の初期化

Swift
var a = [Int](repeating: 0, count: n)   // 0 が n 個
var grid = [[Int]](repeating: [Int](repeating: 0, count: w), count: h)   // h 行 w 列

2 次元は「w 列の行を h 個」の順で書きます。 grid[y][x] のように行、列の順でアクセスします。

ソート

Swift
let asc = a.sorted()                       // 昇順の新しい配列
let desc = a.sorted(by: >)                 // 降順の新しい配列
let bySecond = pairs.sorted { $0.1 < $1.1 }   // タプルの 2 要素目で昇順
a.sort()                                   // a 自体をその場で昇順に

sorted() は並べ替えた新しい配列を返し、元の配列は変わりません。 sort() は配列そのものを並べ替えます。

Dictionary で数える

Swift
var count = [Int: Int]()
for x in a {
    count[x, default: 0] += 1
}

count[キー, default: 0] は、キーがまだなければ 0 とみなす読み方です。 出現回数の集計はこの 3 行で足ります。

Set

Swift
let set = Set(a)             // 重複が消える
set.contains(5)              // 高速な存在判定
let unique = Array(Set(a)).sorted()   // 重複を除いて昇順に

配列の contains は要素数に比例して遅くなります。 存在判定を何度も行うなら、先に Set へ変換してください。

文字列を文字の配列にする

Swift の文字列は、そのままでは s[0] と書けません。 先に Array にするのが定石です。

Swift
let s = Array(readLine()!)   // [Character]
s[0]                         // 先頭の文字
s.count                      // 文字数
String(s.reversed())         // 逆順の文字列

数値と文字列の変換

Swift
let n = Int("42")!                            // 文字列 → 整数
let s = String(42)                            // 整数 → 文字列
let d = Character("7").wholeNumberValue!      // 文字 → 数値
let digits = String(1234).map { $0.wholeNumberValue! }   // 桁ごとに [1, 2, 3, 4]

min / max / 合計

Swift
let mn = a.min()!         // 最小値
let mx = a.max()!         // 最大値
let sum = a.reduce(0, +)  // 合計

空の配列では min()max() が nil を返すので、! はクラッシュします。 要素が 1 つ以上あるときだけ使ってください。

二分探索の雛形

昇順の配列 a の中で、target 以上の値が初めて現れる位置を求めます。

Swift
var lo = 0
var hi = a.count
while lo < hi {
    let mid = (lo + hi) / 2
    if a[mid] < target {
        lo = mid + 1
    } else {
        hi = mid
    }
}
// lo が答え。全要素が target 未満なら a.count になる

無限大の代わりの値

Swift の Int に無限大はないので、十分大きい値で代用します。

Swift
let inf = Int.max / 2

Int.max をそのまま使うと、1 でも足した瞬間にオーバーフローで実行時エラーになります。 足し算する可能性があるなら Int.max / 2 を使ってください。