競プロ備忘録

Swiftでpaizaスキルチェック、問題集をやってます。
ググったものを残してます。

# 入力系
## まとめて入力を受取る
```swift:10000入力を受取る
let inputs = (0..<10000).map { _ in Int(readLine()!)! }
```
map()メソッドは、与えられた範囲内の整数を1つずつ順番に処理していくため、
1回のreadLine()で10000個の入力がまとめて処理されます。
そのため、1つずつ入力を受け取る場合と比較して、入力処理の速度が向上します。

ただし、まとめて入力を受け取る場合には、入力値の数が非常に大きい場合にはメモリに負荷がかかることがあります。
例えば、入力値が数百万、数千万以上になる場合は、まとめて入力を受け取る場合でもメモリ制限に達する可能性があります。
この場合は、バッファリングなどの方法を使用して、メモリ消費量を最小限に抑える必要があります。

```swift:ひとつずつ受取る
var inputs = [Int]()
for _ in 0..<10000 {
    let input = Int(readLine()!)!
    inputs.append(input)
}
```
1つの入力に対して1回のreadLine()を呼び出しています。
つまり、10000回のループで10000回readLine()を呼び出していることになります。
この方法は入力が少ない場合には問題ありませんが、大量の入力を受け取る場合は遅くなるためまとめて受取る方法が良いです。


# 文字列系
## 複数の文字列を配列にバラす
```swift
let str="a a a a a a a"
print(str.split(separator: " ")) // ["a","a","a","a","a","a","a"]

let num="1 2 3 4 5"
print(num.split(separator: " ")) // ["1","2","3","4","5"]
print(num.split(separator: " ").map {Int($0)!}) // [1, 2, 3, 4, 5]
```

## 改行しないで出力
```swift
var i=0
for _ in 0..<1000 { 
    if i != 999 {
        i+=1
        print(i, terminator: " ") //'1 2 3 4 5 6... 997 998 999 '
        } else {
           print(i+1) //'1000\n'
        }
    }
```

## 文字列をスペースで区切る
```swift
//スペースで区切る
print("Samurai", "Engineer", "Blog", separator: " ") // Samurai Engineer Blog
 
let num = 100
print("num =", num, separator: " "); // num = 100
```
参考：[print出力](https://www.sejuku.net/blog/32774)

## 複数入力を配列にして文字列で表示する
```swift
var arr = [String]() // 空の配列
for _ in 0..<10 { 
    let s = readLine()!　// "1"..."9"
    arr.append("\(s)") // 入力内容を配列に格納
}
print(arr) // ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]
let str = arr.joined(separator: "|") // 配列要素を|でくっつける
print(str) // "0|1|2|3|4|5|6|7|8|9"
```

## 文字列を一文字ずつ配列にして分割する
```swift
let rr = "Qiita"
let room = Array(rr)
print(room) // ["Q","i","i","t","a"]
// ※Array(String)変換した配列要素は[Character型]であることに注意する
// var str = [String]()のような宣言をしても型違うエラーでる
// var str = [Character]()ならおk
```
参考：[【swift】文字列を一文字ずつに分割する時のArray("hoge")の型について](https://qiita.com/rondine-jumpei/items/a298bf4e0612166e5dd5)

## 空白をカンマ区切に置換する
```swift
import Foundation // 忘れないように

let input_line=readLine()! // "1 2"
print(input_line.replacingOccurrences(of: " ", with: ",")) // "1,2"
```
## 末尾文字の指定
```swift
import Foundation
let input_line=readLine()! // "1 2 3 4\n"
print("\(input_line.replacingOccurrences(of: " ", with: ",")),") // "1,2,3,4,"
print(input_line.replacingOccurrences(of: " ", with: ","), terminator: ",") // "1,2,3,4/"
```

## 文字列N個出力
```swift:N A B -> "(A, B), *N回繰り返す"
let i=readLine()!.split(separator: " ") // "3 10 99"
let n=Int(i[0])! // 3
for s in 1...n {
    if s < n { 
        print("(\(i[1]), \(i[2]))", terminator: ", ") // "(10, 99), "  
    } else {
        print("(\(i[1]), \(i[2]))") // "(10, 99)"
    }
}

// -> "(10, 99), (10, 99), (10, 99)"
```
## 文字列を連続で出力する
```swift
let i=3
let s="Qiita"
print(String(repeating: "\(s)", count: i)) // "QiitaQiitaQiita"
print(String(repeating: "\(s)\n", count: i)) 
// "Qiita"
// "Qiita"
// "Qiita"
```
## 文字の切り出し
```swift
let str="ABCDEFGH"
print(str.prefix(3)) // "ABC"
```
参考:[【初学者向け】ややこしいSwiftの文字列切り出しの処理を理解する](https://qiita.com/ichikawa7ss/items/42aacdea5622620775e6)

## 指定indexに文字、文字列の挿入
```swift:10文字目で改行させたい
var s="QiitaQiitaQiita"
if s.count > 10 { // もし10文字未満の時insertしようとするとクラッシュするので回避
s.insert(contentsOf: "\n", at: s.index(s.startIndex, offsetBy: 10)) 
// insert(contentsOf: 挿入文字列, at: 場所)
}
print(s) // QiitaQiita\nQiita
```
参考：[Swiftで指定したindexに文字・文字列を挿入する方法](https://swift.tecc0.com/?p=150)
## String配列の1文字目のみ抽出したい(略称)
```swift
let n=4
var s=["qiita", "swift", "kyopro", "xcode", "iosdc"]
for i in 0..<n {

    if i==n-1 {
        print(s[i].prefix(1))
    } else {
        print(s[i].prefix(1), terminator: "")
    }
} //-> qskxi
```

## 文字列から指定位置の文字を取り出す方法
```swift:先頭から任意番目を取得
let str = "Qiita"
let index1 = str.index(str.startIndex, offsetBy: 3) //startIndex:0から3つ進む
    
    //["Q","i","i","t","a"]　Array(str)した際のindexをイメージ
    //[ 0   1   2   3   4 ]  offsetByで指定した数値はどこか確認
print(str[index1]) // t
print(index1)// "_rawBits: 65793" //printするとbit数？がでてくるInt()!は不可。
             //index部分にしか使えなさそう

```
```swift:末尾から任意番目を取得
let str = "ABCDEF"
let index1 = str.index(str.endIndex, offsetBy: -2) //endIndex:0から2つ戻る
    
    //["A","B","C","D","E","F"]　Array(str)した際のindexをイメージ
    //[ -6 -5  -4  -3  -2  -1]  offsetByで指定した数値はどこか確認
print(str[index1]) // E
// 出力の書き方に注意する
```
参考：[【Swift】文字列から指定位置の文字を取り出す方法](https://chusotsu-program.com/swift-index-offset/)

## 文字列を逆順（反転）に並替え
```swift
let str="Qiita"
print(String(str.reversed())) // "atiiQ"
```
## 文字置換
```swift:91を"Qii"へ置換する
import Foundation // 忘れない
let str="91ta91ta91ta"
print(str.replacingOccurrences(of: "91", with: "Qii")) // "QiitaQiitaQiita"
```

## 辞書置換（複数の文字置換）
```swift:母音を消去する
import Foundation // 忘れない
var str="Abeshinzo"
var newStr: String {
// 辞書作成
let dictionary = ["A": "","I": "","U": "","E": "","O": "","a": "","i": "","u": "","e": "","o": ""]
 return dictionary.reduce(str) { $0.replacingOccurrences(of: $1.key, with: $1.value) }
}
print(newStr) //"bshnz"
```
参考：[[Swift]複数の文字列を置換する方法](https://qiita.com/9999/items/df894d0a59d9d743c6f3)

## 文字列検索
```swift:文字列に任意の文字が含まれている時"YES"/含まれていない時"NO"を返す
import Foundation // 忘れない
let i="a"
let str="Qiita"
var flg:Bool=str.contains(i) // ”Qiita”に"a"が含まれる場合True

if flg {
    print("YES")
} else {
    print("NO")
}
```

## 文字列から数値のみ抽出
```swift
let ns="Qiita910"
print(ns.filter("0123456789".contains)) // 919
```

## 特定の文字列が含まれているか（contains）
```swift:Qiitaが含まれているか否か
import Foundation　// 忘れない
let s="Qiita Advent Calendar"

if s.contains("Qiita") {
// contains("抽出文字")があればtrue
    print("Qiitaが含まれています")
} else {
    print("Qiitaが含まれていません")
}
```

## 特定の文字を含まれていれば抽出する
```swift:文字列に "b" が含まれる要素を取得
import Foundation // 忘れない
let strs = [ "ab", "bc", "cd" ]
let results = strs.filter({ $0.contains("b") })
print( results ) // ["ab", "bc"]
```
参考：[Swiftのmap, filter, reduce（などなど）はこんな時に使う！](https://qiita.com/motokiee/items/cf83b22cb34921580a52#filter%E3%81%AF%E6%9D%A1%E4%BB%B6%E3%81%AB%E5%90%88%E3%81%86%E8%A6%81%E7%B4%A0%E3%82%92%E7%B5%9E%E3%82%8A%E8%BE%BC%E3%82%80%E6%99%82%E3%81%AB%E4%BD%BF%E3%81%86)
参考：[【Swift】Array の contains の挙動の整理](https://qiita.com/sugurutakahashi12345/items/42f2c1079316fa175afb)
# 数値系

## 金額表示（カンマ区切り対応）
※長文非対応→Int型でエラーが出るため
```swift
func decimalStyle(priceValue: String) -> String {
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.groupingSeparator = ","
    formatter.groupingSize = 3
    if let priceValue = Int(priceValue) {
        return formatter.string(from: NSNumber(value: priceValue)) ?? "\(priceValue)"
    }
    return priceValue
}


let price = decimalStyle(priceValue: "3000000")
print(price) // 3,000,000
```

## 金額表示、長文lenが3の倍数時限定ゴリ押し出力
```swift
import Foundation

var result : [String] = [] // 空の配列
let str=readLine()! // "123456789"

for i in str {　
    result.append(String(i))　// 文字列を1字ずつの配列にバラす
}

for i in 0..<result.count {   // 1文字ずつループ出力する
    if i % 3 == 0 && i != 0 { // 3で割切れるかつ末尾index以外のとき","挿入かつ改行なし
        print(",", terminator: "")
    } 
    print(result[i], terminator: "") // １文字改行なし
} // -> "123,456,789"
```


## 金額表示（解）　長文、len関係なく対応
```swift
import Foundation

let str="1234567"
var result : [String] = [] // 空の配列
var result2 : [String] = []


for i in str {
    result.append(String(i)) // 文字列を配列化
}
print(result)  // ["1", "2", "3", "4", "5", "6", "7"]
result.reverse()
print(result)  // ["7", "6", "5", "4", "3", "2", "1"]
for i in 0..<result.count {   // 1文字ずつループ出力する
    if i % 3 == 0 && i != 0 { // 3で割切れるかつ末尾index以外のとき","挿入かつ改行なし
        result2.append(",")
    } 
    result2.append(result[i]) 
} 
print(result2)    // ["7", "6", "5", ",", "4", "3", "2", ",", "1"]
result2.reverse() 
print(result2)    // ["1", ",", "2", "3", "4", ",", "5", "6", "7"]
for i in 0..<result2.count {   // 配列ループ出力する
    print(result2[i], terminator: "") // １文字改行なし
}
// -> [1,234,567]
```
## 九九の生成
```swift
for i in 1..<10 {
    for j in 1..<10 {
        if j == 9 {
            print("\(i*j)")
        } else {
            print("\(i*j) " ,terminator: "" )    
        }
    }
}
// ->
1 2 3 4 5 6 7 8 9
2 4 6 8 10 12 14 16 18
3 6 9 12 15 18 21 24 27
4 8 12 16 20 24 28 32 36
5 10 15 20 25 30 35 40 45
6 12 18 24 30 36 42 48 54
7 14 21 28 35 42 49 56 63
8 16 24 32 40 48 56 64 72
9 18 27 36 45 54 63 72 81
```

## 絶対値変換
```swift
let num = -1
print(abs(i)) // 1
```
## mapで配列要素をキャストする
```swift
let n=["8", "10", "1"]
let s=n.map{Int($0)!}
print(s) //[8, 10, 1]
```

## 有効桁数表示
```swift:小数第3位まで表示する
import Foundation // 忘れない
let i=3.14 // Double型
var n = String(format: "%.3f", i) 
print(n) // "3.140"
print(String(format: "%.3f", i)) // "3.140"
```
```swift:整数下2桁切り捨てまるめ
import Foundation
let i=1080
print(i/100*100) // 1000
let s=Double(1080)
print(Int(floor(s/100)*100)) // 1000
```
## ゼロサプレス
```swift
import Foundation // 忘れない
let i=readLine()!.split(separator: " ") // "4 3"
var n = Int(i[0])! // 4
var m = Int(i[1])! // 3

for _ in 0..<n {
    let str=Int(readLine()!)!
    print(String(format: "%\(m)d", str))
} 

入力値
4 3  // 4回入力あり、３桁へゼロサプレス
0
8
81
813

結果
  0
  8
 81
813
```

## 罫線入り九九
```swift
import Foundation // 忘れない
for i in 1..<10 {
    for j in 1..<10 {
        let m = i*j
        let n = String(format: "%02d", m) // ２桁表示統一
        if j == 9 {
            if i==9 {
                print("\(n)")
            } else {
            print("\(n)\n==========================================")
            }
        } else {
            print("\(n)" ,terminator: " | " )    
        }
    }
}
01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09
==========================================
02 | 04 | 06 | 08 | 10 | 12 | 14 | 16 | 18
==========================================
03 | 06 | 09 | 12 | 15 | 18 | 21 | 24 | 27
==========================================
04 | 08 | 12 | 16 | 20 | 24 | 28 | 32 | 36
==========================================
05 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45
==========================================
06 | 12 | 18 | 24 | 30 | 36 | 42 | 48 | 54
==========================================
07 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63
==========================================
08 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72
==========================================
09 | 18 | 27 | 36 | 45 | 54 | 63 | 72 | 81
```
## ペア罫線表出力
```swift
let input_line=readLine()!.split(separator: " ") // "2 3 7 8" -->"h w a b"
let h = Int(input_line[0])!
let w = Int(input_line[1])!
let ab = "(\(input_line[2]), \(input_line[3]))" // "(7, 8)"

var num = (6*w)+(3*(w-1)) // 罫線は上部の文字数と等しくする 
// 文字を連続出力
let s = String(repeating: "=", count: num)

for i2 in 1...h {
    for i in 1...w {
        if i == w {
        print(ab)
            if i2 == h {
            } else {
                print(s)
            }
        } else {
        print(ab, terminator: " | ")
        }
    }
}

(7, 8) | (7, 8) | (7, 8)
========================
(7, 8) | (7, 8) | (7, 8)
```

## 累乗計算
```swift
import Foundation // 忘れない
let input_line=readLine()!.split(separator: " ")　// ”5 3” -> ["5","3"]
let r1=Double(input_line[0])! // 5.0
let r2=Double(input_line[1])! // 3.0
let r3=Int(pow(r1,3)-pow(r2,3)) // pow(Double, 累乗数) 
// 5.0^3 - 3.0^3 = 125.0 - 27.0 = Double:97.0 -> Int:97
print(r3) // 97
powはdouble型でしか使えないことに注意する。
```

## 小数第４位の四捨五入(まるめ)
```swift
import Foundation // 忘れない
let ans=String(format: "%.4f", 1.001999999) // "1.0020"
```
## B電話の距離(リファクタリングしたい)
```swift
import Foundation // 忘れない
var str=Array["0120-44-4444"]
var total = 0

for i in 0..<str.count {
    if str[i]=="-" {
    // 何もしない
    } else {
        if str[i]=="0" {
            total+=24
        }
        if str[i]=="1" {
            total+=6
        }
        if str[i]=="2" {
            total+=8
        }
        if str[i]=="3" {
            total+=10
        }
        if str[i]=="4" {
            total+=12
        }
        if str[i]=="5" {
            total+=14
        }
        if str[i]=="6" {
            total+=16
        }
        if str[i]=="7" {
            total+=18
        }
        if str[i]=="8" {
            total+=20
        }
        if str[i]=="9" {
            total+=22
        }
    }
}
print(total) // 134
```
## 数値配列の追加、削除（キュー）
[問題](https://paiza.jp/works/mondai/stack_queue/stack_queue__queue_step1)
```swift
let q=Int(readLine()!)!
var str=[Int]()
for _ in 0..<q {
    let q1=readLine()!.split(separator: " ")
    if Int(q1[0])!==1 {
        str+=[Int(q1[1])!]
        
        for i in 0..<str.count {
        if i==str.count-1 {
            print(str[i])
        } else {
            print(str[i], terminator: " ")
        }
        }
    } else {
    // キューなのでindex[0]を消す
    str.removeFirst()
        if str==[] {
            print()
        } else {
            for i in 0..<str.count {
            if i==str.count-1 {
            print(str[i])
        } else {
            print(str[i], terminator: " ")
        }
        
    }
    }
} 
}
```

## 数値配列の追加、削除（スタック）
[問題](https://paiza.jp/works/mondai/stack_queue/stack_queue__stack_step1)
```swift 
let n=Int(readLine()!)!
var arr=[Int]()
for _ in 0..<n {
    let m=readLine()!.split(separator: " ")
    // 1のときスタック
    if Int(m[0])!==1 {
    arr+=[Int(m[1])!] //基本追加時は+=がいいかも、append()はString専用
    // 配列中身を半角スペースで表示
    for i in 0..<arr.count {
        if i==arr.count-1 {
            print(arr[i])
        } else {
            print(arr[i], terminator: " ")
        }
    }
    
    } else {
        // 2のときポップ
        arr.removeLast() //最終要素を削除
        // 配列中身がないときは改行のみ出力する
        if arr == [] {
            print()
        } else {
        // 配列中身を半角スペースで表示
        for i in 0..<arr.count {
        if i==arr.count-1 {
            print(arr[i])
        } else {
            print(arr[i], terminator: " ")
        }
    }
    }
}
}
```
参考：[配列の要素の追加や削除について](https://wp-p.info/tpl_rep.php?cat=swift-biginner&fl=r13)
参考：[【Swift】配列操作まとめ](https://qiita.com/REON/items/1f33886d90b4f758e715#%E9%83%A8%E5%88%86%E9%85%8D%E5%88%97%E3%81%AE%E5%9E%8B)


## 進数変換
```swift:10進数→2進数
let num=44
print(String(num, radix: 2)) //001011

```
[Swiftで10進数を2進数・8進数・16進数に変換](https://umadash.hatenadiary.jp/entry/2015/10/17/234253)

# 配列系
## 配列の宣言
```swift:指定要素を初期セット
var numbers = Array(repeating : 0, count : 10) //要素指定で宣言できる
var array = Array(repeating : "Qiita", count : 5)

print(numbers) //[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
print(array) //["Qiita", "Qiita", "Qiita", "Qiita", "Qiita"]
```
## 配列の要素検索
```swift:要素を条件でフィルタする
var array=[1, 2, 3, 4, 5]
var count = array.filter{ $0==5 }.count
print(count) //1
```

## 配列の要素に処理を施す
```swift:mapは全要素に処理を適用したい時つかう
var array=[1, 2, 3, 4, 5]
var array2=array.map { $0 + 100 }
print(array2) // [101, 102, 103, 104, 105]
var strArray=array.map { String($0*100) }
print(strArray) // ["100", "200", "300", "400", "500"]
```

## 配列の要素集計
```swift:reduceは要素集計したいときに使う
var array=[1, 2, 3, 4, 5]
var sum=array.reduce(0,+) //reduce(初期値, combine: 演算子)
print(sum) // 15 合計
var multiplication=array.reduce(1,*)
print(multiplication) // 120 乗算
var average=array.reduce(0, +)/array.count
print(average) // 3 平均
```
## 配列の最大最小
```swift:min()!も同じ感じで使う
var arr=[Int]()
arr+=[5, 7, 3]

var ans=arr.max() // Optional(7)
print(ans!) //　７　（アンラップする）

var ans=arr.max()! // 7 （アンラップする）
print(ans) //　７　
```
参考：[Swiftで配列内で最大の値を取得する方法](https://www.choge-blog.com/programming/swiftarraymaxvalue/)

## 配列に含まれているか
```swift
var array=[1, 2, 3, 4, 5]
array.contains(5) // true
array.contains(10) // fales
```

## 配列の特定の要素番号を取得
```swift
var array=[1, 2, 3, 4, 5]
// 戻り値はオプショナルのためif letを使っている
if let index=array.firstIndex(of:5) {
    print(index) //4 (index番号)
    print(array[index]) //5 (要素値)  
}
```

## 配列の出力
```swift
var array=[1, 2, 3, 4, 5]
for i in array {
    print(i)
}
//1
//2
//3
//4
//5
```

## 配列の逆順出力
```swift:reversedは逆順のふるまいを返す（文字列でもいける）
var array=[1, 2, 3, 4, 5]
for i in array.reversed() {
    print(i)
}
//5
//4
//3
//2
//1

//配列そのものを逆順にするとき
print(array.reverse()) //[5, 4, 3, 2, 1]
```
参考：[【Swift】配列操作まとめ](https://qiita.com/REON/items/1f33886d90b4f758e715#%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9%E6%93%8D%E4%BD%9C)

## 配列の挿入
```swift
var array=[1, 2, 3, 4, 5]
array.insert(10, at:3) //insert(挿入要素, at:挿入index)
print(array) //[1, 2, 3, 10, 4, 5]

array   [1, 2, 3, 4, 5]
at 先頭 0, 1, 2, 3, 4, 5末尾

```

## 要素の削除
```swift
var array=[1, 2, 3, 4, 5]
array.remove(at:3) //remove(at:削除するindex)
print(array) //[1, 2, 3, 5]

var array2=[1, 2, 3, 4, 5]
array2.removeSubrange(1...2) //rengeを指定して削除
print(array2) //[1, 4, 5]

var array3=[1, 2, 3, 4, 5]
array.removeFirst() //先頭要素の削除
print(array3) //[2, 3, 4, 5]

var array4=[1, 2, 3, 4, 5]
array.removeFirst(3) //先頭から3つ要素を削除
print(array4) //[4, 5]

var array5=[1, 2, 3, 4, 5]
array.removeLast() //末尾要素の削除()引数指定で末尾からn個要素削除
print(array5) //[1, 2, 3, 4]

var array6=[1, 2, 3, 4, 5]
array.removeAll() //全要素削除
print(array6) //[]

var array7=[3, 1, 2, 3, 4, 5, 3]
array.removeAll(where: {$0==3}) //要素を指定して削除
print(array7) //[1, 2, 4, 5] //要素3がすべてないなった

```
参考：
[【Swift】配列から条件に一致した要素を削除する方法](https://kita-note.com/swift-array-drop-conditions)
[Swift の Array（配列）- 要素の削除](https://softmoco.com/swift-basics/swift-array-remove.php)

疑問
- removeFirst()とdropFirst()の違いについて
- [公式ソース：dropfirst(_:)](https://developer.apple.com/documentation/swift/array/dropfirst(_:))
- [公式ソース2：removefirst()](https://developer.apple.com/documentation/swift/array/removefirst())
- 戻り値に違いあり（Self.SubSequenceとSelf.Element）
- そもそもSubSequenceってなんだ？




# 条件系
## データ有無
```swift
let arr=["Oiita","iita"]
if arr.isEmpty {
    print("データが存在します") //-> データが存在します
} else {
    print("データがありません")
}

let arr2=[String]()
if arr2.isEmpty {
    print("データが存在します") 
} else {
    print("データがありません") //-> データがありません
} 
```
## switch文
```swift
let i=5

switch i {
    case 1:
    print("E")
    case 2:
    print("D")
    case 3:
    print("C")
    case 4:
    print("B")
    case 5:
    print("A")
    default:
    print()
}
// -> "A"
```
参考:[SwiftにおけるSwitchまとめ](https://qiita.com/akatsuki174/items/2720ebc369a6c1d9f629)

```swift:ループ内のswitch
let arr=[100, 10, 60, 79]

for i in 0..<arr.count {
    let num=arr[i]

    switch num {
        case (80...100): //caseは範囲指定できる
        print("A")
        
        case (70...79):
        print("B")
        
        case (60...69):
        print("C")
        
        default:
        print("D")
    } //switchここまで
}
// "A"
// "D"
// "C"
// "B"
```
参考：[Swift さくっと確認したい基礎文法 [いろんな条件分岐(switch文、if文)]](https://qiita.com/yuinchirn/items/b88c2b4094df76ce9608)

## While無限ループ
```swift:while trueは夢幻列車、ブレーク条件を必ず書く
var i = 0
while true {
    i+=1
    if 4 < i {
       break
    }
    if i==2 {
       continue
    }
    print(i)
}
// 1 3 4
```
```swift
let h=Int(readLine()!)!
var p=[0, 1, 1] 
var m=[0, 1, 1]
var dmg=2
var i=2

while h > dmg {  // while 条件式成立するならループ
    p[0] = p[1]
    p[1] = p[2]
    m[0] = m[1]
    m[1] = m[2]
    p[2] = m[0] + m[1]
    m[2] = p[0] + 2*p[1]
    dmg += m[2]
    i += 1
}
 print(i)
```
慣れないとスライドする思考は難しそう。

# スタック・キュー
## 最大区間の和
問題：[最大の区間和 Swift編](https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step2)
```swift:リフト
let nx=readLine()!.split(separator: " ") // 4 2
let n=Int(nx[0])! // 数値の数　　 4
let x=Int(nx[1])! // 加算する数 2
let s=readLine()!.split(separator: " ") // 2 3 4 1

var add=[Int]()
for i in 0..<n {
    add+=[Int(s[i])!] // [2 ,3, 4, 1]
}
var max_sum=0
var tmp_sum=0
var left_num=add[0] // 2

//初期区間の合計
for i in 0..<x {
    max_sum+=add[i]
}
tmp_sum=max_sum //初期区間の和 5


//残り区間のリフト計算
for r in 0..<n-x {
    tmp_sum-=add[r] //先頭を引く
    tmp_sum+=add[r+x] //次の値を足す
    
    if max_sum<tmp_sum  { //区間の和以上のなった時更新
        left_num=add[r+1] //r+1が区間の和先頭のindex
        max_sum=tmp_sum
        } 
}
print("\(max_sum) \(left_num)")　// 7 3
```
## 逆ポーランド記法
参考：[【考察】なぜ Swift に `popLast()` があって `popFirst()` がないのか](https://qiita.com/lovee/items/7d617dcb4e83df9d7b58)
問題：[逆ポーランド記法 Swift編](https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step3)
```swift
let n=7
var arr=["1","2","+","3","4","+","-"]
var tmp=[Int]() // セット用配列
var num1=0 
var num2=0

for i in 0..<n {
    if arr[i]=="+" || arr[i]=="-" { // pop条件
        num1=tmp.popLast()!
        num2=tmp.popLast()!
        if arr[i]=="+" {
            tmp.append(num1+num2)
        } else {
            tmp.append(num2-num1)
        }
    } else {
        tmp.append(Int(arr[i])!)
    }
}
print(tmp[0])
```
<B>imege
<img width='400' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/1d34f058-d605-c2f2-fec6-f9d16c0f3756.png'>


## エスカレーター
問題：[エスカレーター Swift編](https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step5)
```swift
let nk=readLine()!.split(separator: " ")
let n=Int(nk[0])!
let k=Int(nk[1])!
var en=readLine()!.split(separator: " ")
let enlast=Int(en.last!)!
var arr=[String]()
var cnt=0

for _ in 0..<k {
    arr+=[""] //k要素の配列を作成
}


for i in 1...enlast {
     arr.removeFirst() // 先頭を削除

     if i==Int(en[0])! { // i番目がen[0]と同じとき追加
        cnt=0
        arr+=[String(en[0])]
        en.removeFirst() // 先頭を削除
        
        for a in 0..<arr.count {
            if arr[a] != "" {
                cnt+=1 //空白以外ならカウントアップ
             }
         }
         print(cnt)
     } else {
         arr+=[""]
     }
}    
```
<B>imege
<img width='450' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/95a2545c-ddd7-415c-e848-1f314c12340b.png'>

## 箱とボール
問題：[箱とボール](https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step6)
removeFirst()はO(n)に対してremoveLast(),popLast()はO(1)に注目する
```swift
let n=Int(readLine()!)!
var s=readLine()!.split(separator: " ")
var arr=[Int]()

for i in 0..<n {
    arr+=[Int(s[i])!]
   
    while arr.count>=2 { //arr要素2以上で回す
        let top2=arr.popLast()!
        let top1=arr.popLast()!        
        if top1==top2 { 
            //同じ値は倍にして追加
            arr+=[top1*2]    
        } else {
            //異なる値はそれぞれ追加
            arr+=[top1]
            arr+=[top2]
            break //異なるtop1,top2を追加したらループ終了
        }
    }
}

for _ in 0..<arr.count {
    print(arr.popLast()!)
}
```
<B>imege
<img width='400' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/65961997-3807-1e9d-978c-4f93a8f857c2.png'>

# スタック・キュー応用編
## 3 つのスタック
問題：[3 つのスタック](https://paiza.jp/works/mondai/stack_queue_advanced/stack_queue_advanced__three_stack)
```swift
import Foundation
let n=Int(readLine()!)!
var stack1=[Int]()
var stack2=[Int]()
var stack3=[Int]()

for _ in 0..<n{
    let a=readLine()!
    if a.contains("push"){
        let push=a.split(separator: " ")
        if push[1]=="1"{
            stack1+=[Int(push[2])!]
        } else {
            if push[1]=="2"{
                stack2+=[Int(push[2])!]
            } else {
                stack3+=[Int(push[2])!]
            }
        }
    } else {
        let pop=a.split(separator: " ")
        if pop[1]=="1"{
            stack1.popLast()!
        } else {
            if pop[1]=="2"{
                stack2.popLast()!
            } else {
                stack3.popLast()!
            }
        }
    }
}

if stack1.isEmpty==false {
    for s1 in stack1.reversed(){
        print(s1)
    }
}

if stack2.isEmpty==false {
    for s2 in stack2.reversed(){
        print(s2)
    }
}

if stack3.isEmpty==false {
    for s3 in stack3.reversed(){
        print(s3)
    }
}
```
「配列逆順ですべて出力」答えの出力が分かりにくかった。
先頭と末尾だけ出力すればよいと解釈していた。

## warp
問題：[warp](https://paiza.jp/works/mondai/stack_queue_advanced/stack_queue_advanced__warp)
```swift
import Foundation

// 入力から2つの数字（n, k）を取得
let nk = readLine()!.split(separator: " ").map{ Int($0)! }
let n = nk[0] // nを代入
let k = nk[1] // kを代入

// 配列 to の宣言
// to[i][j]はi行j列目を表す
// toはn行k列を持ち、初期値が0の2次元配列
var to = [[Int]](repeating: [Int](repeating: 0, count: k), count: n)

// 現在の位置を記録する変数 now の宣言
var now = 0

// Sは移動先を記録する
var S: [Int] = []

// n行分繰り返す
for i in 0..<n {
    // i行目の入力を取得して配列 toi に代入
    let toi = readLine()!.split(separator: " ").map{ Int($0)! }

    // k列分繰り返す
    for j in 0..<k {
        // toi のj番目を-1してto[i][j]に代入
        to[i][j] = toi[j] - 1
        }
    }

    // Sの配列に初期値0を追加
    S.append(0)

// k回繰り返す
for i in 0..<k {
    // 現在地（now）から移動先（to[now][i]）が-2の場合（=戻る）
    if to[now][i] == -2 {
        // Sの配列の末尾（最後に移動した場所）を削除
        S.removeLast()
        // Sの配列の末尾（一つ前に移動した場所）を現在地とする
        now = S.last!
    } else {
        // 移動先を現在地とする
        now = to[now][i]
        // 移動先をSの配列に追加
        S.append(now)
    }
// 現在地を出力する
print(now + 1)
}
```

```swift
toはnマスをk回移動するための初期セット
to[i][j]
var to = [[Int]](repeating: [Int](repeating: 0, count: 5), count: 5)
// 出力例
[
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0],
  [0, 0, 0, 0, 0]
]
```
<B>image</B>
<img width='800' src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/618527/be03aed8-a22b-6c9b-5dce-3f5509ed77f2.png'>
問題が上記フローとなることを理解するのに1週間以上要した。
日本語難しいです。

# クエリメニュー
## 平方分割
問題：[平方分割](https://paiza.jp/works/mondai/query_primer/query_primer__square_division)
```swift
// 10000の平方根を初期セット
let BLOCK_SIZE = 100
// k値の入力
let k = Int(readLine()!)!
// 10000の値をまとめて受取る
let inputs = (0..<10000).map { _ in Int(readLine()!)! }

// 前処理: 各ブロックの最大値を計算する
// 要素を事前に宣言することで時短になる
// (blockMax+=[]では遅くなる)
var blockMax = [Int](repeating: -100000, count: 100)
for i in 0..<10000 {
    // ブロックのインデックスを計算する
    let blockIndex = i / BLOCK_SIZE
    blockMax[blockIndex] = max(blockMax[blockIndex], inputs[i])
}

// k個のクエリをまとめて受取る
let queries = (0..<k).map { _ in readLine()!.split(separator: " ").map { Int($0)! } }

// クエリを高速に処理する
for query in queries {
    let l = query[0] - 1
    let r = query[1] - 1
    let lBlock = l / BLOCK_SIZE
    let rBlock = r / BLOCK_SIZE
    var res = -100000

    // 区間が同じブロック内の場合
    if lBlock == rBlock {
        for i in l...r {
            res = max(res, inputs[i])
        }
    } else {
    // 複数の区間にブロックがまたがる場合
        // 左端ブロックの最大値を計算
        for i in l...((lBlock + 1) * BLOCK_SIZE - 1) {
            res = max(res, inputs[i])
        }

        // 右端ブロックの最大値を計算
        for i in (rBlock * BLOCK_SIZE)...r {
            res = max(res, inputs[i])
        }

        // 中間ブロックの最大値を計算
        for i in (lBlock + 1)..<rBlock {
            res = max(res, blockMax[i])
        }
    }
    // 結果を出力する
    print(res)
}
```
- `let blockIndex = i / BLOCK_SIZE`部分は`if i % BLOCK_SIZE==0{}`にしても差は微小、ブロックのインデックスを計算するという処理の意図が明確なのは前者。
- max()関数を使用する場合は、各ブロックの最大値を計算するたびに、既存の最大値と比較して、より大きい方を保存する。max()関数を使用しない場合と比べて最大値を求めるために必要なループ回数が減り、処理が高速化される。
- 後半クエリ処理の部分でkが9000以上のときビルドパフォーマンス不足に悩んだ。
- 与えられたクエリに対して高速な処理を行うためには、ブロックサイズを適切に設定し、ブロックごとに最大値を予め計算するという方法が有効。

## 点と幅
問題：[点の幅](https://paiza.jp/works/mondai/query_primer/query_primer__range_of_score)
```swift
let nk = readLine()!.split(separator: " ").map { Int($0)! }
let n = nk[0]
let k = nk[1]

// 生徒の得点
let inputs = (0..<n).map { _ in Int(readLine()!)! }
// 生徒番号の範囲
let queries = (0..<k).map { _ in readLine()!.split(separator: " ").map { Int($0)! } }

for query in queries {
    // 生徒番号の始点終点
    let aStart = query[0] - 1
    let aEnd = query[1] - 1
    let bStart = query[2] - 1
    let bEnd = query[3] - 1
    // 得点の範囲    
    let aRange = inputs[aStart...aEnd]
    let bRange = inputs[bStart...bEnd]
    // 最低点最高点
    let aMin = aRange.min()!
    let aMax = aRange.max()!
    let bMin = bRange.min()!
    let bMax = bRange.max()!
    // 得点の差異
    let aDiff = aMax - aMin
    let bDiff = bMax - bMin
    // 差異比較と結果出力
    if aDiff == bDiff {
        print("DRAW")
    } else if aDiff > bDiff {
        print("A")
    } else {
        print("B")
    }
}

``` 
- 自分で作成した際はmin(),max()を使わずにaRange,bRangeをループしてif文にした(ケース4：0.59秒)
- 上記コードのmin(),max()関数を利用することでループとif文が減ってパフォーマンスが最適化(ケース4：0.36秒)
- 問題からどんな風にコードに落とし込むかスムーズに考えられた
  
# ソート系
- sort()の["100", "101", "120"]など並べ替えできないのはなぜ？
参考：[Swift文字列と数字で配列をソート](https://www.web-dev-qa-db-ja.com/ja/arrays/swift%E6%96%87%E5%AD%97%E5%88%97%E3%81%A8%E6%95%B0%E5%AD%97%E3%81%A7%E9%85%8D%E5%88%97%E3%82%92%E3%82%BD%E3%83%BC%E3%83%88/832707225/)
- 基本はInt変換してソート
- 文字列でソートするときは参考内容を参照

## 配列の並べ替え
- sortは破壊的ソート(配列元を上書きする)
- sortedは非破壊的ソート(配列元はそのまま保持)
参考：[Swiftで配列(Array)をソート(sort, sorted)](https://easyramble.com/sort-array-with-swift.html)
```swift
var languages: [String] = ["Swift", "Java", "Ruby", "Javascript", "PHP"]
languages.sort()
print(languages) //["Java", "Javascript", "PHP", "Ruby", "Swift"]

var numbers: [Int] = [3, 1, 4, 1, 5, 9, 2]
numbers.sort()
print(numbers) //[1, 1, 2, 3, 4, 5, 9]

// 降順はsort(by: >), 昇順はsort(by: <)
numbers.sort(by: >)
print(numbers) //[9, 5, 4, 3, 2, 1, 1]

// 明示的に記述するならクロージャ
numbers.sort(by: { $0 < $1 }) // 昇順
numbers.sort(by: { $0 > $1 }) // 降順

```
参考：[Swift の Array（配列）- 要素の並べ替え](https://softmoco.com/swift-basics/swift-array-sort.php#1)

## タプルソート
```swift:任意の文字列を降順ソート
var str:[(Int,Int)]=[]

for _ in 0..<2 {
    let n=readLine()!.split(separator: " ") // "1 3", "2 2"
    str.append((Int(n[0])!,Int(n[1])!)) 
    // -> str = [(1,3), (2,2)]   
}
 str.sort(by: {return $0 > $1}) //　降順ソート 隣通しを比較してる
// タプル場所を指定しないと1番目が同数のとき2番目でも降順ソートしている？要検証

for i in 0..<str.count {
print("\(str[i].0) \(str[i].1)") // タプルのindex指定は.index番号
}
```

```swift:[(String,Int)]でInt順にソートする
var arr=[(_:String,num:Int)]() //空タプル宣言
arr+=[("Qiita", 1), ("kyopro", 1001), ("paiza", 9), ("tuple", 20), ("array", 100)]

arr.sort(by:  {return $0.num < $1.num } ) //タプルIntの昇順ソート
// {return $0.num < $1.num } //.ラベルで数値比較を順番やっている

print(arr) // [("Qiita", 1), ("paiza", 9), ("tuple", 20), ("array", 100), ("kyopro", 1001)]
```
参考：[【swift】二次元配列をソートする](https://qiita.com/BMJr/items/0907136643028860f420)

### タプルのmax、min
A.最大値最小値をセットするのと、B.ソートして$0と$Nを指定するのだとどっちが速い？
A.はmaxのとき不等号の向き要注意！
後から見返したときどんな処理をしているかはAの方が分りやすいかも
```swift:max,min
//A
var items: [(name: String, number: Int)] = [("banana", 234), ("apple", 423), ("grape", 142)]
let max = items.max(by: { (a, b) -> Bool in
    return a.number < b.number //ここの不等号の向き要注意！
})
let min = items.min(by: { (a, b) -> Bool in
    return a.number < b.number
})
print("\(max!), \(min!)")
// -> (name: "apple", number: 423), (name: "grape", number: 142)

//B
var items2 = items.sorted(by: {return $0.1 > $1.1} )
print("\(items2[0]), \(items2[items2.count-1])")
// -> (name: "apple", number: 423), (name: "grape", number: 142)
```
参考：[Swift：配列のmax(by:),min(by:)の使い方](https://qiita.com/Kyome/items/486738fa497674a11fa6)

## タプル検索
```swift
var taple=[("A", 3), ("B", 1), ("C", 6)]
let users=["A","B","C"]
print("１回目")
for i in 0..<users.count {
//条件合致のタプルindexを代入
    if let index=taple.firstIndex(where: { $0.0 == users[i]}) {
    print("\(users[i])のスタミナは残り\(taple[index].1)回です")
    //taple[index]を利用して値の変更も可能
    taple[index].1=taple[index].1-1
    }
}
print("２回目")
for i in 0..<users.count {
//条件合致のタプルindexを代入
    if let index=taple.firstIndex(where: { $0.0 == users[i]}) {
    print("\(users[i])のスタミナは残り\(taple[index].1)回です")
    }
}
	
//１回目
//Aのスタミナは残り3回です
//Bのスタミナは残り1回です
//Cのスタミナは残り6回です
//２回目
//Aのスタミナは残り2回です
//Bのスタミナは残り0回です
//Cのスタミナは残り5回です
```
参考：[【swift】 タプルの配列で指定した要素のindexを取得する。](https://qiita.com/BMJr/items/b4ceeb425eeebfe6b286)

# 辞書　
[問題はここから](https://paiza.jp/works/mondai/c_rank_level_up_problems/c_rank_dictionary_boss)
|row|p|q|r||row|p|q|r|
|-|-|-|-|-|-|-|-|-|
|1|2|2|2||1|2|3|4|
|2(ab)|2|1|||2(ab)|1|3|
|3(ab)|1|2|||3(ab)|2|1|
|4(bc)|1|1|||4(bc)|2|3|
|5(bc)|2|2|||5(bc)|3|3||
||||||6(bc)|1|4|||
||||||||||
|ans(ac)|1|2|||ans(ac)|1|3|
|ans(ac)|2|1|||ans(ac)|2|4|

問題文を理解するのが大変だった

```swift:AB, BCが与えられるので -->ACを求める
let input_line=readLine()!.split(separator: " ")
let p=Int(input_line[0])!
let q=Int(input_line[1])!
let r=Int(input_line[2])!
var ab=[(Int,Int)]()
var bc=[(Int,Int)]()

for _ in 0..<p {
    let a=readLine()!.split(separator: " ")
    ab.append((Int(a[0])!,Int(a[1])!))
}
ab.sort(by: {return $0 < $1}) // 昇順sort

for _ in 0..<q {
    let b=readLine()!.split(separator: " ")
    bc.append((Int(b[1])!,Int(b[0])!)) // cb順に並べてcの昇順にする
}
bc.sort(by: {return $0 < $1}) // 昇順sort

for v in 0..<p {
    for i in 0..<q {
        if ab[v].1==bc[i].1 { // a b==b c 共通のbをkeyにして出力する
            print("\(ab[v].0) \(bc[i].0)")
            break
        }
    } 
}
```
## 辞書のソート＆出力(順序付き辞書)

```swift
dic=[("bcd", 4), ("abc", 1)] //辞書のままだと順不同
let sortedDic = dic.sorted() { $0.key < $1.key } //文字で降順、配列化する
//配列みたいに{ $0.0 < $1.0 }でもできる
//keyソートなら(by: <)も可能
print(sortedDic) 
//[(key: "abc", value: 1), (key: "bcd", value: 4)]

for (key, value) in sortedDic {
    print("\(key) \(value)")
}
//abc 1
//bcd 4
```
参考：[[Swift] 順序付き辞書、DictionaryLiteral](https://qiita.com/a-beco/items/46e7e25b5f56263fb58f)
[【Swift】辞書型(Dictionary)をキー値でソートさせる方法!sortedメソッドの使い方](https://tech.amefure.com/swift-dictionary-sort)

## 辞書の要素毎に値をセットする
```swift:辞書のKeyを指定して0...9のカウントアップする
let n=5
let str=["1", "2", "3", "3", "6"]
var num: [String: Int] = ["0": 0, "1": 0, "2": 0, "3": 0, "4": 0, "5": 0, "6": 0, "7": 0, "8": 0, "9": 0] //辞書で0...9の<Key:cnt>を宣言

for i in 0..<str.count {
    let a=String(str[i]) //index部分にセットするKey値
    num[a]!+=1 //辞書Key指定して特性したValueはOptional型だからアンラップする
}              //print(num["0"])  -> Optional(0)
               //print(num["0"]!) -> 0

for i in 0...9 {
    if i==9 {
        print(num[String(i)]!)
    } else {
        print(num[String(i)]!, terminator: " ")
    }
}
// 0 1 1 2 0 0 1 0 0 0

for (key, value) in num { //こんな風にも表せるが順番はハチャメチャ
  print("\(key): \(value)", terminator: " ")
}
//6: 1 7: 0 8: 0 9: 0 0: 0 2: 1 4: 0 5: 0 3: 2 1: 1 

print(num)//順番ははちゃめちゃ
//["5": 0, "0": 0, "4": 0, "7": 0, "6": 1, "9": 0, "1": 1, "2": 1, "3": 2, "8": 0]
```
辞書KeyはIntの方がラク？Key指定時に
参考：[辞書 | Dictionary型 - Swiftの始め方](https://swift.codelly.dev/guide/%E3%82%B3%E3%83%AC%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E5%9E%8B/%E8%BE%9E%E6%9B%B8.html)

## 辞書のprint方法
[英小文字の出現率](https://paiza.jp/works/mondai/data_structure/data_structure__dict_step2)
ごり押しせずにArrayキャストかつsortedで順番に出力できる
```swift
let n=Int(readLine()!)!
let str=Array(readLine()!)
var check: [String:Int]=["a":0, "b":0, "c":0, "d":0, "e":0, "f":0, "g":0, "h":0,
            "i":0, "j":0, "k":0, "l":0, "m":0, "n":0, "o":0, "p":0, "q":0, "r":0,
            "s":0, "t":0, "u":0, "v":0, "w":0, "x":0, "y":0, "z":0]
for i in 0..<str.count {
    let key=String(str[i])
    check[key]!+=1
}

print("\(check["a"]!) \(check["b"]!) \(check["c"]!) \(check["d"]!) ", terminator: "") 
print("\(check["e"]!) \(check["f"]!) \(check["g"]!) \(check["h"]!) \(check["i"]!) ", terminator: "")
print("\(check["j"]!) \(check["k"]!) \(check["l"]!) \(check["m"]!) \(check["n"]!) ", terminator: "")
print("\(check["o"]!) \(check["p"]!) \(check["q"]!) \(check["r"]!) \(check["s"]!) ", terminator: "")
print("\(check["t"]!) \(check["u"]!) \(check["v"]!) \(check["w"]!) \(check["x"]!) ", terminator: "")
print("\(check["y"]!) \(check["z"]!)")
```
参考：[[Swift] Dictionaryをこねくり回すネタ集](https://qiita.com/Saayaman/items/e82a09f93bb91409e446#sort)

## 辞書の要素追加
[価格の算出](https://paiza.jp/works/mondai/data_structure/data_structure__dict_step4)
```swift
let nm=readLine()!.split(separator: " ").map{Int($0)!} //"3 4"から["3", "4"]から[3, 4]へ変換 
let n=nm[0]
let m=nm[1]

var dic=[String:Int]()

for _ in 0..<n {
    let ab=readLine()!.split(separator: " ")
    dic[String(ab[0])]=Int(ab[1])! //辞書keyに対してvalueをセット
    //keyが存在しないなら追加され、存在する場合valueが更新する
}

var chkList=[String]()
for _ in 0..<m {
    let s=readLine()!
    chkList+=[s]
}

for i in chkList {
    if dic[i]==nil { //この書き方はもっとよくできそう↓参照
        print(-1)
    } else {
        print(dic[i]!)
    }
}

//改善したスマート
for i in chkList {
    print(dic[i] ?? -1)
}
```
参考：[【Swift入門】Dictionaryの要素を更新・追加・削除する方法](https://www.sejuku.net/blog/31390)

## 辞書key,value存在チェック
[商品の検索](https://paiza.jp/works/mondai/data_structure/data_structure__dict_boss)
```swift
let nq=readLine()!.split(separator: " ").map {Int($0)!}
let n=nq[0]
let q=nq[1]
var sarr=[String:Int]()

for i in 1...n {
    let s=readLine()!
    if sarr.keys.contains(s) { //keyがあればtrue
       //何もしない key重複時はvalue更新したくない
    } else {
         sarr[s]=i //初出keyのみvalue追加
    }
}

for _ in 0..<q {
    let q=readLine()!
    print(sarr[q] ?? -1) //辞書keyよりvalue表示
}
```
参考：[Swift の Dictionary（辞書）- キーと値のペア数とキーの存在確認](https://softmoco.com/swift-basics/swift-dictionary-inspect.php#:~:text=Swift%20%E3%81%A7%20Dictionary%EF%BC%88%E8%BE%9E%E6%9B%B8%EF%BC%89%E3%81%AB,()%20%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%81%8C%E4%BD%BF%E3%81%88%E3%81%BE%E3%81%99%E3%80%82)

## valueが複数要素の辞書
問題：[銀行 Swift編](https://paiza.jp/works/mondai/query_primer/query_primer__bank)
辞書は順序保持できないため登録順番をValueへ追加した
SPMで[Collection](https://github.com/apple/swift-collections)を利用できる場合は[OrderedDictionary](https://zenn.dev/treastrain/articles/e4bac83e2cc5a6)で順序保持できそう
```swift
let nk=readLine()!.split(separator: " ").map {Int($0)!}
let n=nk[0]
let k=nk[1]
var array = [String:[Int]]()
// 銀行名:[暗証番号,残高,登録順)で辞書作成
for i in 0..<n{
    let q=readLine()!.split(separator: " ")
    let companyName=String(q[0])
    let password=Int(q[1])!
    let balance=Int(q[2])!
    array[companyName]=[password,balance,i]
}

for _ in 0..<k{
    let t=readLine()!.split(separator: " ")
    let companyName=String(t[0])
    let password=Int(t[1])!
    let balance=Int(t[2])!
    // 暗証番号一致のとき(array[]?[index]この書き方は辞書独特なのか.じゃないので注意)
    if password==array[companyName]?[0] {
        // 残高更新する(valueの数値を利用するときアンラップが必要)
        array[companyName]=[password,(array[companyName]?[1])!-balance,(array[companyName]?[2])!]
    }
}
// 登録順昇順ソート
for (key,value) in array.sorted(by: { $0.value[2] < $1.value[2] }){
    print("\(key) \(value[1])")
}
```

## value配列の要素追加
問題：[経理 Swift編](https://paiza.jp/works/mondai/query_primer/query_primer__accounting)
`var allArray=[String: [(String,Int)]]()の場合、keyは順不同だがvalueは順番を保持できる`
`要素追加はallArray[key]?.append(value)`

```swift
let nk=readLine()!.split(separator: " ").map {Int($0)!}
let n=nk[0]
let k=nk[1]
var postArray=[String]()
var allArray=[String: [(String,Int)]]() // (部課):[(注文番号,経費)]
for _ in 0..<n{
    let post=readLine()!
    postArray+=[post]
    // keyを先に作成しておく
    allArray[post]=[("",0)]
}
for _ in 0..<k{
    let costs=readLine()!.split(separator: " ")
    let post=String(costs[0])
    let order=String(costs[1])
    let cost=Int(costs[2])!
    // key指定してvalue要素を追加 allArray[post]?+=[(order,cost)]も同じ
    allArray[post]?.append((order,cost))
}

for key in postArray{
    print(key)
    // valueのindex0番目("",0)を除外
    for value in allArray[key]! {
        if value.0 != "" {
        print("\(value.0) \(value.1)")
        }
    }
    print("-----")
}
```
当初for _ in 0..<k{...}の中でallArrayを下記のように作ろうとしたところタイムオーバーになった
下記のようなforループ内でのcontains()は極力避けたほうが良い
```swift
if allArray.keys.contains(post)==false {
    // keyがなければ新規
    allArray[post]=[(order,cost)]
} else {
    // keyがあれば要素追加
    allArray[post]?.append((order,cost))
}
```

# Set型
- 一意な値を格納する
- 順序関係は保証されない
- 論理演算（積集合など）はSetがはやい
- 集合の生成（追加など）はArrayがはやい
参考：
[Swift の Set（セット）で集合の演算](https://softmoco.com/swift-basics/swift-set-operation.php#1)
[Setは遅いのか](https://qiita.com/KyoheiG3/items/0bf9887a55fe7ad05811)
[Setを使いこなしたい（願望）](https://qiita.com/hmhmsh/items/3d2d8715a3b43e90af9b#%E5%8C%85%E5%90%AB%E9%96%A2%E4%BF%82)
## Setで配列値の重複チェック
```swift:arr1とarr2の重複値を出す
var arr1=[1, 14, 3, 20, 6, 12, 14]
var arr2=[14, 12, 11, 18]

//ArrayからSet型へキャスト
var setarr1=Set(arr1) //重複値はなくなる
print(setarr1) //[1, 14, 3, 20, 6, 12]
var setarr2=Set(arr2) //順番もかわる
print(setarr2) //[12, 11, 18, 14]

//積集合
var setarr3=setarr1.intersection(setarr2)
print(setarr3) //[14, 12]

//和集合
var setarr4=setarr1.union(setarr2)
print(setarr4) //[11, 1, 14, 18, 3, 20, 6, 12]

//差集合
var setarr5=setarr1.subtracting(setarr3) //setarr1から重複値を削除する
print(setarr5) //[3, 6, 20, 1]

//要素が含まれているかチェック
print(setarr4.contains(14)) //true
print(setarr4.contains(0)) //false

//集合要素の追加・削除
print(setarr3.insert(100)) //[12, 14, 100]
print(setarr3.remove(12)) //[100, 14]
```
```swift:Set型宣言とArrayキャスト
let a: Set<Element> = 値
let a: Set<Int> = [1,2,3]
let a: Set<Int> = [] //空集合
let a = Set<Int>() //空集合

let arr=Array(a) //配列へキャスト
```
## 動的配列
[動的配列 Swift編](https://paiza.jp/works/mondai/data_structure/data_structure__array_boss)
```swift
import Foundation //忘れない
let nq=readLine()!.split(separator: " ")
var a=readLine()!.split(separator: " ").map{String($0)}//一括[String]変換

let n=Int(nq[0])!
let q=Int(nq[1])!

for _ in 0..<q {
    var q1=0 //for内と外どちらで宣言する方が良い？
    var q2=""
    
    let qry=readLine()!
    if qry.contains("0") {
        let qrysplit=qry.split(separator: " ")
        q1=Int(qrysplit[0])!
        q2=String(qrysplit[1])
    } else {
        q1=Int(qry)!
    }
    
    
    if q1==0 {
        // push_back x
        a.append(q2)
    }
    if q1==1 {
        // push_back x
        a.popLast()!
    }
    if q1==2 {
        //print
        for s in 0..<a.count {
            if s==a.count-1 {
                print(a[s])
            } else {
                print(a[s], terminator: " ")
            }
        }
    } 
}
```
## 配列の要素毎に値をセットする
[数値の出現率](https://paiza.jp/works/mondai/data_structure/data_structure__dict_step1)
初見ではfor文で多重ループ処理してごり押した。

```swift:配列のindexを指定して0...9のカウントアップする
let n=5
let str=["1", "2", "3", "3", "6"]
var arr=[0,0,0,0,0,0,0,0,0,0] //0...9の１０要素カウント用配列
for i in 0..<str.count {
    arr[str[i]]+=1 //strの値をarr[index]として+1する
}

for i in 0..<arr.count {
    if i==arr.count-1 {
        print(arr[i])
    } else {
        print(arr[i],terminator: " ")
    }
}
// 0 1 1 2 0 0 1 0 0 0
```
# 構造体
## 構造体の検索
[構造体の検索](https://paiza.jp/works/mondai/class_primer/class_primer__find)
```swift
struct User:Equatable{ //この問題ではEquatableなしでも通る
    var nickname : String;
    var old : String;
    var birth : String;
    var state : String;
}

let n=3 //任意の数
var arr=[User]() // Userを格納する配列
for _ in 0..<n {
    let qry=readLine()!.split(separator: " ").map {String($0)}
    let test=User(nickname: qry[0],old: qry[1], birth: qry[2], state: qry[3])
    arr+=[test]
}
let o="23" //年齢を探す

var ans=arr.first(where: { $0.old==o }) //構造体内で最初に該当する要素indexを取得
print(ans!.nickname) //アンラップしてから指定する
```
[【Swift】構造体の要素を検索してインデックスを取得する方法！](https://tech.amefure.com/swift-struct-index)

## 構造体の更新
[構造体の更新](https://paiza.jp/works/mondai/class_primer/class_primer__change)
```swift
struct User{ 
    var stid : Int; //ユニークなIDをセット
    var nickname : String;
    var old : String;
    var birth : String;
    var state : String;
}

let nk=readLine()!.split(separator: " ").map {Int($0)!}
let n=nk[0]
let k=nk[1]
var arr=[User]()

for i in 1...n {
    let qry=readLine()!.split(separator: " ").map {String($0)}
    let test=User(stid:i, nickname: qry[0],old: qry[1], birth: qry[2], state: qry[3])
    arr+=[test]
}

for _ in 0..<k {
    let ann=readLine()!.split(separator: " ").map {String($0)}
    let stid=Int(ann[0])!
    let nn=ann[1]
    changeName(index:stid, chgName:nn)
}

func changeName(index:Int, chgName:String) {
    arr[index-1].nickname=chgName //arrのindex番号はstid-1となる
    //配列のindex番号を指定して該当行のnicknameを更新する
}

for i in 0..<arr.count {
    print("\(arr[i].nickname) \(arr[i].old) \(arr[i].birth) \(arr[i].state)")    
}
```
参考：[【Swift】構造体の要素を検索してインデックスを取得する方法！](https://tech.amefure.com/swift-struct-index)

# クラス
## クラスの作成
[クラスの作成](https://paiza.jp/works/mondai/class_primer/class_primer__make_class)
```swift
class Employee {
    let number:Int //初期値があればinit()はいらない？
    let name:String //初期値なしの場合はinit()必須
    var array=[(Int,String)]()
    
    init() {
        self.number=0
        self.name=""
    }
    
    func make(number:Int,name:String) {
        array+=[(number,name)]
    }
    
    func getnum(num:Int) {
        print(array[num-1].0)
    }
    
    func getname(num:Int) {
        print(array[num-1].1)
    }
}


let n=Int(readLine()!)!

var c=Employee() //Employeeクラスを使えるようにする

for _ in 0..<n {
    let s=readLine()!.split(separator: " ")
    let f=String(s[0])
    let number=Int(s[1])!
    
    if f == "make" {
        c.make(number:number, name:String(s[2]))
    } else {
        if f == "getnum" {
            c.getnum(num:number)
        } else {
            c.getname(num:number)
        }
    }
}
``` 

# Activity history
|date|value|
|--|--|
|2022/09/15|Swift スキルチェックDランク始動|
|2022/11/08|問題集：Cランクレベルアップメニュー修了|
|2022/11/24|スキルチェックDランク問題218問修了|
|2022/11/28|ランクB達成|
|2022/11/29|問題集：スタック・キューメニュー修了|
|2022/12/06|paiza課金開始|
|2022/12/12|問題集：データセット選択メニュー修了|
|2022/12/27|問題集：論理演算メニュー修了|
|2023/01/06|問題集：配列活用メニュー修了|
|2023/03/23|問題集：クエリメニュー修了|


# つまづいたら見に行く
[競技プログラマのためのSwiftチートシート](https://zenn.dev/koher/articles/swift-cheatsheet-for-competitive-programming)