INDEX
■はじめに
Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)
(5/23時点の方針)
メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。
■問題
●出典
AtCoder Beginner Contest 064のA問題
https://atcoder.jp/contests/abc064/tasks/abc064_a
●問題文
AtCoDeer君は、赤、緑、青色のカードを持っています。
それぞれのカードには 1 以上 9 以下の整数が書かれており、赤色のカードには r、緑色のカードには g、青色のカードには b が書かれています。
3 つのカードを左から順に赤、緑、青色の順に並べ、左から整数を読んだときにこれが 4 の倍数であるか判定しなさい。
●制約
- 1≤r,g,b≤9
●入力
入力は以下の形式で標準入力から与えられる。
r g b
●出力
AtCoDeer君が作った 3 桁の整数が 4 の倍数ならば YES
、そうでないならば NO
を出力しなさい。
■回答
●愚直に書く
愚直に考えると、3つの数字を連結して3桁の数字にして、% 4
をしてあまりゼロになればYesという感じか。
n = gets.split.map(&:to_i).join.to_i
puts n % 4 == 0 ? "Yes" : "No"
あれ、通らない。。。
と思ったら超凡ミス、YES
NO
とすべきところをYes
No
としていた涙。
n = gets.split.map(&:to_i).join.to_i
puts n % 4 == 0 ? "YES" : "NO"
通った!
to_i
してjoin
してまたto_i
するのが無駄な気がする。下記のように手直し。
n = gets.split.join.to_i
puts n % 4 == 0 ? "YES" : "NO"
通った!
●メソッド化して書く
メソッドを作る練習のために、あえてそういう書き方をする。
def main
n = read_nums
puts is_multiple4?(n)
end
def is_multiple4?(n)
n % 4 == 0 ? "YES" : "NO"
end
def read_nums
gets.split.join.to_i
end
main
通った!
●リファクタリング/別アプローチ
3桁目(100の位)は計算する必要がない(必ず4の倍数になる)ので、2桁分だけを処理するというのを思いついたけど、どうやるんだろ…。
標準入力を3つの変数にそれぞれ入れて、2つめと3つめだけを連結して計算していけばよいのか。
r, g, b = gets.split
puts (g + b).to_i % 4 == 0 ? "YES" : "NO"
通った!!
もうちょっとスマートな方法、例えば3の倍数なら「3つの数字を足し合わせたものが3の倍数なら3桁の数字も3の倍数になる」という法則を使えるけど、4の倍数でもそういった法則を何か使えるのだろうか…。
思いつかないので、他の方の回答を見ることにする。
●他の方の回答例
考え方としては上位の方々も同じだった。
join
じゃない方法で連結する方法としてdelete
やgsub
を使っていたのでそれぞれ確認。
n = gets.delete(" ").to_i
puts n % 4 == 0 ? "YES" : "NO"
gets.delete(" ")
で、半角スペースを削除した形で取得できる。なるほど。
n = gets.gsub(" ","").to_i
puts n % 4 == 0 ? "YES" : "NO"
gets.gsub(" ","")
で、半角スペースを「何もなし」に置き換えした形で取得できる(つまりdelete
と同じ)。なるほど。
●出てきたメソッド等
公式リファレンスを見る訓練。
-
String#delete
https://docs.ruby-lang.org/ja/latest/method/String/i/delete.html -
String#gsub
https://docs.ruby-lang.org/ja/latest/method/String/i/gsub.html
■振り返りなど
delete
やgsub
など、いくつかの方法を確認できて良かった。