はじめに
Ruby学習の一環として「競技プログラミング(競プロ)」に挑戦します。
そのための学習の中で学んだことをアウトプットしていきます。
今回は「AtCoder Beginners Selection」の二問目(Product)より。
https://atcoder.jp/contests/abs
問題
2つの正整数a,bが与えられます。
aとbの積が偶数か奇数か判定してください。
制約
1≤a,b≤10,000
aとbは整数
入力は以下の形で与えられる。
a b
# 例
2 3
積が奇数なら Odd 、偶数なら Even と出力せよ。
出力例
# 上記例の場合
Even
解答①
まずは僕が最初に書いたコードです。
a,b = gets.chomp.split(" ").map(&:to_i)
c = a * b
if c % 2 == 0
print "Even"
else
print "Odd"
end
前回の学習で学んだメソッド(gets chomp split map)を使って入力を受け取り、
あとはif文で…という感じ。
AtCoder Beginners SelectionでRuby学習【PracticeA】標準入力
ただ他の方の解答を見てみると、2行で完結している方もいて、そっちの方がかっこいい!
ので、どんな記法を用いて書いているのか、いくつか見てみたいと思います。
解答② 三項演算子
a, b = gets.chomp.split.map(&:to_i)
(a*b%2==0) ? puts('Even') : puts('Odd')
入力を受け取るまではほぼ同じで、
後半は三項演算子を用いた記述方法ですね。
条件が複雑でない場合は、こちらの方が良さそうです。
三項演算子
条件式 ? 真の時の値 : 偽の時の値
解答③ odd?メソッド even?メソッド
a,b = gets.split(" ").map(&:to_i)
(a*b).even? ? (puts "Even") : (puts "Odd")
解答②で学んだ三項演算子を使いつつ、
代数演算子「%」ではなく、aとbの積をodd?メソッドもしくはeven?メソッドを使って
直接判定しちゃおうという方法。
例
#even?メソッド
10.even?
=> true
#odd?メソッド
10.odd?
=> false
ここから下は1行で記述が完結する解答です。
ざっとみた感じ、共通する考え方は「aかbのどっちかが偶数なら結果も偶数じゃん」ということ。
積ではなく、入力された整数について判定を行っています。
解答④ all?メソッド
all?メソッドは配列の要素を繰り返し実行し、返り値が全て真の時にtrueを返します。
puts gets.split.map(&:to_i).all?(&:odd?) ? "Odd" : "Even"
奇数を判定するodd?メソッドで配列の要素の判定を行い、
全て奇数であれば、trueを返すため"Odd"、一つでも偶数があれば、falseを返し、"Even"となります。
最後に最も短いコードでの解答です。
解答⑤ 正規表現
puts gets[/[02468]\b/]?:Even: :Odd
詳しい説明は今の僕には難しいので省きますが、
ここでは入力されてくる様々な文字列のパターンのうち
「末尾が偶数のもの」をメタ文字も用いつつまとめて表現し判定を行っているようです。
以下が正規表現で表現された部分
[/[02468]\b/]
ここで使われているメタ文字の意味は以下の通り。
メタ文字 | 意味 | 解答における役割 |
---|---|---|
[...] | 括弧内のいずれか 1 文字 | 括弧内のいずれか 1 文字 |
/.../ | 囲まれた文字列を正規表現とする | 囲まれた文字列を正規表現とする |
\b | 先頭もしくは末尾とマッチ | 解答例では末尾とマッチ |
最後に
以上、AtCoder Beginners SelectionでRuby学習【Product】から学んだ様々な記法をご紹介しました。
コードの長さやメモリも判定されるみたいなので、簡潔に短い解答を意識していきたいですね。
もし間違いなどございましたら、ご指摘いただけると嬉しいです。