ABC121 C Energy Drink Collector,D XOR WorldをKotlinで解いてみた話
irisruneです。自己紹介でも軽く触れましたがKotlinが面白そうだったので過去問はだいたいKotlinでやります。
今日のテーマはちょっと軽めですがABC121のC問題とD問題。あと一応AtCoderで使うKotlinについて。
ABC121-C
やるだけソートの実装力が9割くらいの問題です。
class Store(val a : Long, val b : Long) fun main(args: Array<String>){ var(n, m) = readLine()!!.split(" ").map(String::toLong) var l = mutableListOf<Store>() for(i in 1..n){ val (a, b) = readLine()!!.split(" ").map(String::toLong) l.add(Store(a, b)) } l.sortBy { it.a } var sum = 0L l.forEach{ sum += it.a * listOf(it.b, m).min()!! m = listOf(0, m - it.b).max()!! } println(sum) }
想定解と同じだしアルゴリズム面で言うこともあまりないと思うので簡単なコードレビューを。
- MutableListは別にvarにする必要はないのでvalにするべき。
- 単純な整数2つの組ならクラスを作るなんて仰々しいことをしなくてもPairでなんとかなる。
- 入力値のmを直接変化させるのは微妙?forEach部分をメソッドに分離してmを値渡しすればすっきりしそう。
ABC121-D
XORの性質を理解しているかどうか…というよりはを求める発想ができるかの方が強いと思います。D問題にしては比較的簡単な方です。
fun f(x : Long) : Long{ return when(x % 4){ 0L -> x 1L -> 1L 2L -> x + 1L else -> 0L } } fun main(args: Array<String>){ var (a, b) = readLine()!!.split(" ").map(String::toLong) println(f(a - 1).xor(f(b))) }
解法に行き着く過程としてはこんな感じでした。
- 愚直にやるのは時間かかるので無理。
- 時間で解けるを使ってみたいに表せるのでは?
- XORの性質上2.はだいたい正しい。
- をで列挙したら法則性が見つかったので解けた。
解説ではは排他的論理和の性質から数学的に導けるとありましたが、いずれにせよでの場合分けに行き着くと思います(ととで二回分岐するのも本質的に同じなので)。
あとはコードレビュー。
- (a, b)はvalにするべき。
- (x % 4)は(x % 4L)にするべき。
型関連はバグの原因になるので気を付けましょう。今回はセーフでした。
(pure)Kotlin(v1.0)のポイント
(2019/03/05現在)AtCoderではKotlin1.0しか使えません。これはどの辺に影響してくるかというと例えば
val minA = minOf(A1, A2)
が使えないので、(pure)Kotlinで書くならば
val minA = listOf(A1, A2).min()
という形に。Java関数を使えば別に不自由しないと思うんですがせっかくなのでJava関数は(なるべく)使わない方針で。
でもkotlin.mathが使えないのは代替案が思いつかないのでjava.lang.Math使います。つらい。