1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AOJ ITP1 を Kotlin で - Branch on Condition 編

Posted at

はじめに

コーディングの基礎体力づくりとして取り組んでいる、AOJ ITP1 の学習記録です。
今回は、"Branch on Condition" を題材に Kotlin の言語機能そのものにフォーカスしました。

基本的な if 文から、Kotlinの強みである when 式やメソッドチェーンを活用した、より簡潔で表現力豊かなコードの書き方までを記録しています。

Branch on Condition

2_A: Small, Large, or Equal

2 つの整数 $a$ と $b$ の大小関係を判定し、a < b、a > b、a == b のいずれかを出力する問題です。

提出したコード

fun main() {
    val (a, b) = readLine()!!.split(" ").map { it.toInt() }

    if(a < b){
        println("a < b")
    } else if(a > b){
        println("a > b")
    } else
        println("a == b")
}

2_B: Range

3 つの整数 $a, b, c$ が $a < b < c$ の条件を満たしているか判定し、Yes または No を出力する問題です。

提出したコード

fun main() {
    val (a, b, c) = readLine()!!.split(" ").map(String::toInt)

    println(if(a < b && b < c) "Yes" else "No")
}

2_C: Sorting Three Numbers

与えられた 3 つの整数を昇順(小さい順)に並べ替えて出力する問題です。

提出したコード

fun main() {
    val items = readLine()!!.split(" ").map (String::toInt)

    println(items.sorted().joinToString(" "))
}

2_D: Circle in a Rectangle

長方形の中に円が完全に含まれているかを判定する問題です。

提出したコード

fun main() {
    val (w, h, x, y, r) = readLine()!!.split(" ").map(String::toInt)

    println(if(x - r >= 0 && x + r <= w && y - r >= 0 && y + r <= h) "Yes" else "No")
}

番外編

今回は Kotlin の言語仕様を最大限に活かした書き方にチャレンジしてみました。

より Kotlin らしい書き方へ

2_A のリファクタリング

fun main() {
    val (a, b) = readLine()!!.split(" ").map(String::toInt)

    // if式と同様にwhenも値を返す「式」として使える
    println(when {
        a < b -> "a < b"
        a > b -> "a > b"
        else -> "a == b"
    })
}

map { it.toInt() }map(String::toInt) への変更

  • ラムダ式を メソッド参照 に置き換えることによって「各要素に toInt() を適用する」意図をより直接的に表せる
  • 型推論が効いた状態で「StringtoInt を呼ぶ」ことが明示され、何を変換しているかがコード上で明確になる

if-else if-elsewhen 式 への変更

  • Kotlin では whenif式(Expression) として値を返せる
  • 各分岐で値を返すため、println() の呼び出しを1箇所にまとめられる

2_C のリファクタリング

fun main() {
    // メソッドチェーンで、データが変換されていく流れを表現
    readLine()!!
        .split(" ")
        .map(String::toInt)
        .sorted()
        .joinToString(" ")
        .let(::println)   // 最終結果をprintlnで出力
}

中間変数 val items の削除

  • 一度しか使わない変数への代入を省略することで、コードの行数を減らし、読み手の認知負荷を低減できる

メソッドチェーンの改行

  • .split.map.sorted などのメソッド呼び出しを改行で区切ることで、データがどのように変換されていくのかが一目でわかる
  • デバッグ時のコメントアウトや処理の入れ替えが容易になる

スコープ関数 let と関数参照 ::println の活用

  • スコープ関数 let を使うと、直前の処理結果をそのまま引数として渡すことができる
  • joinToString(" ") の結果を let に渡し、さらにそれを 関数参照 ::println を使って println 関数の引数として直接渡すことで、流れるようなデータ処理を表現できる

おわりに

今回、Kotlin の if が文ではなく として扱えることを学びました。
TypeScript では if であるため、この違いが Kotlin に三項演算子が存在しない理由なのだと理解できました。
また、スコープ関数関数参照 といった機能を初めて使ってみましたが、これらを活用することで、より Kotlin らしい簡潔なコードが書けることを実感しました。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?