コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 064 A – RGB Cards

  • by

■はじめに

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じゃない方法で連結する方法としてdeletegsubを使っていたのでそれぞれ確認。

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と同じ)。なるほど。

●出てきたメソッド等

公式リファレンスを見る訓練。

■振り返りなど

deletegsubなど、いくつかの方法を確認できて良かった。