AtCoderをやる中で、自分に足りない考え方のようなものが1つわかってきた。
それは、「if式を使わずに、メソッド1つで求める値を出す」ということ。
今までやった中でmax
メソッドでこれを実現する方法が2回出てきたので、ブログにまとめることにする。
■例1:xとyのうち大きい方を表示
●お題
「任意に与えられた整数x
とy
のうち、大きい方を表示せよ」
みたいなお題だとする。
※元ネタはAtCoderのこれです https://atcoder.jp/contests/abc002/tasks/abc002_1
●レベル1
if x > y
puts x
else
puts y
end
日本語をそのまま書き下すとこうなる、という感じ。これはこれで全く悪くないと思うけど、もっとスマートに書きたい。
●レベル2
レベル1をリファクタリングすると、例えばこうなる。
puts x > y ? x : y
- 単純なif分岐は、三項演算子にできる。
- putsを外側に置くことで、putsの重複記述を防ぐ。
この書き方も、スッキリしていて良い。
●レベル3
そして、自分に足りないのがこの考え方。
puts [x, y].max
配列の中で最大のものを出すというmax
メソッドを使うことで、if分岐させる必要がなくなる。
うまく言えないんだけど、なんかこういう書き方がカッコいいな〜と思う。
■例2:xとyのどちらかに1を足して積が最大となるようにする
●お題
「任意に与えられた整数x
とy
がある。どちらかに1を足して、足してない方との積が最大となるようにし、その積を表示せよ」
みたいなお題だとする。
※元ネタはAtCoderのこれです https://atcoder.jp/contests/abc031/tasks/abc031_a
●レベル1
if x <= y
puts (x + 1) * y
else
puts x * (y + 1)
end
問題文を咀嚼すると、「xとyのうち小さい方に1を足して、足してない方とかける(xとyが同じ場合はどっちに足しても一緒なので、xの方に足すことにする)」となる。 この日本語をそのまま書き下すと上記のようになる。これも悪いわけではないけど、もっとスマートに書きたい。
●レベル2
レベル1をリファクタリングすると、例えばこうなる。
puts x <= y ? (x + 1) * y : x * (y + 1)
- 単純なif分岐は、三項演算子にできる。
- putsを外側に置くことで、putsの重複記述を防ぐ。
- 例1と全くおなじ考え方
スッキリはしたけど、例1に比べて三項演算子がややこしくなってきた。例1ではレベル2と3にあまり違いがなかったような気がするけど、今回は後述するレベル3がより良く思えてきた。
●レベル3
これも例1と同じようにmax
メソッドを使う。
puts [(x + 1) * y, x * (y + 1)].max
2つとも計算してしまって、max
メソッドで大きい方を出力すればOK、という考え方。
ifでコツコツ書くより、なんか洒落てる気がする。
■おわりに
書いて気づいたけど、例1と例2は、ちょっとだけ条件が異なるだけで、全く同じ話だった汗。もう1個くらい思い当たる例があった気がするんだけどなんだったかな…。 なんにせよこういう考え方で書けるようになるには訓練するしかないので、いつも気に留めながらたくさんコードを書いて身につけていきたい。
ちなみに、必ずしもifを使わずにmaxで書くのが正しいわけではないとも思う。max
メソッドの方は計算を2回してからmax
してるので、中の計算がものすごく大変な場合には、ifでまず条件分岐して、必要な方の計算だけをする方が望ましいこともあるかもしれない。
その辺の良し悪しを判断するスキルも付けていきたいな〜。