競プロで使える便利なエクステンション一覧(Swift)

私はSwiftにおける競プロの記事をいくつか投稿しています。

- [競プロで使える標準入力の便利メソッド一覧](https://qiita.com/uhooi/items/b8cebb638e9bf5ac9556)
- [競プロで使える標準エラーの出力方法](https://qiita.com/uhooi/items/f490d14602a7bc114948)
- 競プロで使える便利なエクステンション一覧 __←イマココ__
- [競プロで使えるアルゴリズム関数一覧](https://qiita.com/uhooi/items/d4998e90f3f2fed01e68)

自分で武器を増やしていくのが競プロの面白さのひとつだと思っているので、まずは自分で考えるのがオススメです。
どうしてもわからないときに、私の記事が参考になると嬉しいです :relaxed:

## はじめに

本記事は [Swift/Kotlin愛好会 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/love_swift_kotlin) の11日目の記事です。
空いているので埋めました。

競プロで使える便利な拡張メソッドとコンピューテッドプロパティを紹介します。

## 注意

- 本記事で紹介しているソースコードが正しいかは保証できていません。
- 本記事は随時更新予定です。

## 環境

- OS：macOS Big Sur 11.1
- Xcode：12.3 (12C33)
- Swift：5.3.2  
5.2.1（2021/01/24現在のAtCoder）でも動作する

## 競プロで使える便利なエクステンション一覧

### 桁分割

<details><summary>説明</summary><div>

数値の桁を分割し、桁数の降順に整列した配列で返します。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
private extension Numeric where Self: LosslessStringConvertible {
    var digits: [Int] { string.digits }
}
private extension LosslessStringConvertible {
    var string: String { String(self) }
}
private extension StringProtocol {
    var digits: [Int] { compactMap { $0.wholeNumberValue } }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
1.digits -> [1]
32.digits -> [3, 2]
445.digits -> [4, 4, 5]
62096.digits -> [6, 2, 0, 9, 6]
```

</div></details>

<details><summary>参考リンク</summary><div>

- [Swift - Intを個々の桁に分割する](https://www.366service.com/jp/qa/daa0f49d5da31fc8ec972fb46a24988d)
- [提出 #18780201 - AtCoder Beginners Selection](https://atcoder.jp/contests/abs/submissions/18780201)

</div></details>

### 合計

<details><summary>説明</summary><div>

配列などシーケンスの要素の合計を返します。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
private extension Sequence where Element: AdditiveArithmetic {
    func sum() -> Element {
        reduce(.zero, +)
    }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
[1].sum() -> 1
[1, 3].sum() -> 4
[1, 3, 4].sum() -> 8
(1...5).sum() -> 15
```

</div></details>

<details><summary>参考リンク</summary><div>

- [swift/Integers.swift at main · apple/swift](https://github.com/apple/swift/blob/main/stdlib/public/core/Integers.swift#L41-L45)

</div></details>

### Decimal→Int変換

<details><summary>説明</summary><div>

`Decimal` を `Int` に変換します。

私は `pow()` の戻り値を `Int` で欲しいときに使います。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
import Foundation

private extension Decimal {
    var intValue: Int { NSDecimalNumber(decimal: self).intValue }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
pow(2, 3).intValue -> 8
pow(10, 6).intValue -> 1000000
```

</div></details>

<details><summary>参考リンク</summary><div>

- [init(decimal:) | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/nsdecimalnumber/1412692-init)
- [intValue | Apple Developer Documentation](https://developer.apple.com/documentation/foundation/nsnumber/1407153-intvalue)

</div></details>

### 10進数→2進数変換

<details><summary>説明</summary><div>

10進数の数値を2進数の文字列に変換します。
`digit` に必要十分な大きさの値を渡さないとオーバーフローするので注意です。

まだAtCoderでは使ったことがありません。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
private extension FixedWidthInteger {
    func binaryString(digit: Int) -> String {
        var result: [String] = []
        for i in 0..<(Self.bitWidth / 8) {
            let byte = UInt8(truncatingIfNeeded: self >> (i * 8))
            let byteString = String(byte, radix: 2)
            let padding = String(repeating: "0", count: 8 - byteString.count)
            result.append(padding + byteString)
        }
        return String(result.reversed().joined().suffix(digit))
    }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
0.binaryString(digit: 2) -> "00"
1.binaryString(digit: 2) -> "01"
2.binaryString(digit: 4) -> "0010"
8.binaryString(digit: 8) -> "00001000"
255.binaryString(digit: 8) -> "11111111"
256.binaryString(digit: 8) -> "00000000" // !!!: オーバーフロー
256.binaryString(digit: 12) -> "000100000000"
```

</div></details>

<details><summary>参考リンク</summary><div>

- [FixedWidthInteger | Apple Developer Documentation](https://developer.apple.com/documentation/swift/fixedwidthinteger)
- [Swiftで整数から2進数文字列が欲しいときは FixedWidthInteger を使おう - Qiita](https://qiita.com/yosshi4486/items/54d18a04401154a79e47)

</div></details>

### 素数判定

<details><summary>説明</summary><div>

整数が素数か判定します。

まだAtCoderでは使ったことがありません。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
private extension Int {
    var isPrime: Bool {
        guard self > 1 else {
            return false
        }
        return (2..<self).lazy.filter { self % $0 == 0 } .count == 0
    }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
1.isPrime -> false
2.isPrime -> true
3.isPrime -> true
4.isPrime -> false
5.isPrime -> true
```

</div></details>

<details><summary>参考リンク</summary><div>

- [素数 - Wikipedia](https://ja.wikipedia.org/wiki/素数)
- [提出 #173625 | アルゴ式](https://algo-method.com/submissions/173625)

</div></details>

### 回文判定

<details><summary>説明</summary><div>

整数または文字列が回文か判定します。

まだAtCoderでは使ったことがありません。

</div></details>

<details><summary>ソースコード</summary><div>

```swift
private extension Int {
    var isPalindrome: Bool { String(self).isPalindrome }
}

private extension String {
    var isPalindrome: Bool { self == String(self.reversed()) }
}
```

</div></details>

<details><summary>出力例</summary><div>

```
1.isPalindrome -> true
2.isPalindrome -> true
10.isPalindrome -> false
11.isPalindrome -> true
100.isPalindrome -> false
101.isPalindrome -> true
```

</div></details>

<details><summary>参考リンク</summary><div>

- [回文 - Wikipedia](https://ja.wikipedia.org/wiki/回文)
- [提出 #175165 | アルゴ式](https://algo-method.com/submissions/175165)

</div></details>

## おわりに

以上、 [Swift/Kotlin愛好会 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/love_swift_kotlin) の11日目の記事でした。

## 参考リンク

- [uhooi/Programming-Swift-Solving: Solve competition programming using Swift.](https://github.com/uhooi/Programming-Swift-Solving)