AtCoder B,C問題をKotlinで解こう - ABC244

当記事ではAtCoder、ABCのB問題ならびにC問題（時々D問題も）のKotlinでの解法を超初心者向けに詳細に解説します。

https://atcoder.jp/contests/abc244/tasks

## [B - Go Straight and Turn Right](https://atcoder.jp/contests/abc244/tasks/abc244_b)
#### やりたいこと
座標上で **位置** と **向き** を保持し、入力値によって状態を変化させる。最終的な **位置** が答えとなる。

#### 入力値の取得
```Kotlin
    val n = readLine()!!.toInt()
    val s = readLine()!!
```
#### 位置の保持
位置（x値とy値）を保持するdata classを作成しよう。
```Kotlin
data class Loc(val x: Int, val y: Int)
```
#### 向きの保持
東西南北を保持するenum classを作成しよう。
```Kotlin
enum class Dir {
    N,
    E,
    S,
    W
}
```
#### 操作の反映
入力値による状態の変化を実装しよう。
![244_b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2597866/45cc832e-6fd9-a208-05d9-b85934eb2559.png)

クラス Loc に位置変更処理を実装しよう。
```Kotlin
data class Loc(val x: Int, val y: Int) {
    // "S" が入力された時の位置変更処理
    fun forward(dir: Dir): Loc {
        return when (dir) {
            Dir.N -> {
                Loc(x, y + 1)
            }
            Dir.E -> {
                Loc(x + 1, y)
            }
            Dir.S -> {
                Loc(x, y - 1)
            }
            Dir.W -> {
                Loc(x - 1, y)
            }
        }
    }
}
```

enum クラス Dir に向きの変更処理を実装しよう。
```Kotlin
// 方向変更処理をやりやすくするため、向きの値にユニークな数値を設定する
enum class Dir(private val id: Int) {
    N(0),
    E(1),
    S(2),
    W(3);

    // "R" が入力された時の方向変更処理
    fun turn(): Dir {
        return values().first { it.id == (this.id + 1) % 4 }
    }
}
```

#### サンプルコード
```Kotlin:main.kt
fun main(args: Array<String>) {
    val n = readLine()!!.toInt()
    val s = readLine()!!
    // 初期の位置 x=0, y=0
    var cur = Loc(0, 0)
    // 初期の向き 東向き
    var dir = Dir.E
    for (i in s) {
        if (i == 'S') {
            cur = cur.forward(dir)
        } else {
            dir = dir.turn()
        }
    }
    println("${cur.x} ${cur.y}")
}


data class Loc(val x: Int, val y: Int) {
    // "S" が入力された時の位置変更処理
    fun forward(dir: Dir): Loc {
        return when (dir) {
            Dir.N -> {
                Loc(x, y + 1)
            }
            Dir.E -> {
                Loc(x + 1, y)
            }
            Dir.S -> {
                Loc(x, y - 1)
            }
            Dir.W -> {
                Loc(x - 1, y)
            }
        }
    }
}

// 方向変更処理をやりやすくするため、向きの値にユニークな数値を設定する
enum class Dir(private val id: Int) {
    N(0),
    E(1),
    S(2),
    W(3);

    // "R" が入力された時の方向変更処理
    fun turn(): Dir {
        return values().first { it.id == (this.id + 1) % 4 }
    }
}
```

## [C - Yamanote Line Game](https://atcoder.jp/contests/abc244/tasks/abc244_c)
#### やりたいこと
1. 入力値からNを受け取る
2. 1..2N+1の範囲の数値のうち、未使用のものを出力する
3. 1..2N+1の数値を受け取って、使用済みとする
4. 2~3を繰り返す
3. 0が入力されたらプログラム終了

#### 出力する数値をどうやって決めるか？
Nの値は最大1000とあまり大きくはないので使える数値のリストを作ろう。
1. 使える数値のリストから1つ選んで出力する（とりあえず先頭を出力するので問題ない）
1. 使える数値のリストから出力に使った数値を削除する
1. 入力値を受け取る
1. 使える数値のリストから、入力された数値を削除する

以上を繰り返していこう。

#### Nの取得
```Kotlin
    val n = readLine()!!.toInt()
```

#### 使える数値のリスト作成
1..2N+1の数値のリストを作成しよう。数値に重複はないので、MutableSetで作成しよう。
```Kotlin
    // 使える数値のリスト
    val flag = (1..(n * 2 + 1)).toMutableSet()
```
#### サンプルコード
```Kotlin:main.kt
fun main(args: Array<String>) {
    val n = readLine()!!.toInt()
    // 使える数値のリスト
    val flag = (1..(n * 2 + 1)).toMutableSet()
    while (flag.isNotEmpty()) {
        // 使える数値リストから、出力予定の数値を一つ取得
        val tmp = flag.first()
        // 使える数値リストから出力予定の数値を削除
        flag.remove(tmp)
        // 数値を出力
        println(tmp)
        // 入力値を受け取る
        val tmp2 = readLine()!!.toInt()
        if (tmp2 == 0) {
            // 入力値が0の場合は処理終了
            return
        }
        // 使える数値リストから入力値の数値を削除
        flag.remove(tmp2)
    }
}
```