はじめに
Ruby学習の一環として「競技プログラミング(競プロ)」に挑戦します。
そのための学習の中で学んだことをアウトプットしていきます。
今回は「AtCoder Beginners Selection」の四問目(Shift only)より。
https://atcoder.jp/contests/abs
自分が使った解法と、他の方の解法を比べながらまとめていきます。
問題
N個の正の整数A1,...,ANが与えられます。
この整数が全て偶数である時、次の操作を行います。
・整数全てを2で割ったものに置き換える。
最大何回操作を行えるか求めなさい。
制約
1 ≤ N ≤ 200
1 ≤ Ai ≤ 10**9
入力は以下の形で与えられる。
N
A1 A2 ... AN
# 例
3
8 12 40
上記の例だと最大2回割ることができるので
出力例
# 上記例の場合
=> 2
解答①
まずは僕が最初に書いたコードです。
count = 0
N = gets.to_i
lists = gets.split(" ").map(&:to_i)
while lists.all?(&:even?) do
lists.map!{ |x| x / 2 }
count += 1
end
print count
第一回の問題で学んだメソッド(gets split map)を使って入力を受け取り、
AtCoder Beginners SelectionでRuby学習【PracticeA】標準入力
第二回で学んだメソッド(all? even?)で判定を行いつつ、
AtCoder Beginners SelectionでRuby学習【Product】様々な解法から学ぶ
while文やmap!メソッドを使って解答しました。
まずは、ここで初めて使ったwhile文、map!メソッドについてまとめていきます。
while文
条件式が真である間は、指定した処理を繰り返します。
while 条件式 do
実行する処理1
実行する処理2
end
今回の解答では、偶数判定を行う「even?メソッド」を「all?メソッド」を使って配列の要素全てにあて、
全て偶数である場合には、指定した処理を行うようにしました。
map!メソッド
配列の要素を、処理結果で上書きします。
配列の入った変数.map! { |変数名| 処理内容 }
#例
lists = [10, 20]
lists.map!{ |x| x / 2 }
print lists
=> [5, 10]
ちなみに、
入力の時に使用しているmapメソッドでは、
配列の上書きは行われません。戻り値として配列を生成しています。
#例
lists = [10, 20]
print lists.map{ |x| x / 2 }
=> [5, 10]
print lists
=> [10, 20]
以下は他の方の解答になります。
解答② mapメソッドで操作の回数(解答)を戻り値として戻す
配列の要素を「2で割れる回数」にして配列として戻し、
その要素の中で最も小さい数を「minメソッド」を使って出力しています。
gets
puts gets.split(" ").map{|f|
f=f.to_i
c=0
while f%2==0
f/=2
c+=1
end
c
}.min
minメソッド(Arrayクラス)
配列の最小の要素を戻します。
#例
lists = [35, 10, 20]
print lists.min
=> 10
最後に
以上、AtCoder Beginners SelectionでRuby学習【Shift only】から学んだメソッドをご紹介しました。
他の方の解答も見れるのが便利ですね。かなり勉強になります。
もし間違いなどございましたら、ご指摘いただけると嬉しいです。