INDEX
■はじめに
Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)
(5/23時点の方針)
メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。
■問題
●出典
AtCoder Beginner Contest 047のA問題
https://atcoder.jp/contests/abc047/tasks/abc047_a
●問題文
競プロ幼稚園に通う 2 人の子供がキャンディーの取り合いをしています。
3 個のキャンディーパックがあり、それぞれのパックにはキャンディーが a, b, c 個入っています。
えび先生はこの 3 個のパックを、キャンディーの個数が等しくなるように 2 人に分けようとしています。そのような分け方が可能かどうかを判定してください。
ただし、キャンディーをパックから取り出すことはできず、それぞれのパックをそのままどちらかの子供にあげる必要があります。
●制約
- 1≦a,b,c≦100
●入力
入力は以下の形式で標準入力から与えられる。
a b c
●出力
キャンディーを同じ個数に分けられるなら Yes
を、そうでなければ No
を出力せよ。
■回答
●愚直に書く
全部合計して2で割ったときに一番大きい数字になればYes、かな?
a, b, c = gets.split.map(&:to_i).sort
puts (a + b + c) / 2 == c ? "Yes" : "No"
行けると思ったけどダメだった、、、 1つだけWA
になってしまった。
あ〜〜〜わかった、奇数の時に2で割ると小数点が繰り上げられて数が狂うんだな。2
で割るところを2.0
にすれば小数点第一位まで計算できるはず。
a, b, c = gets.split.map(&:to_i).sort
puts (a + b + c) / 2.0 == c ? "Yes" : "No"
通った!!!
●メソッド化して書く
メソッドを作る練習のために、あえてそういう書き方をする。今回は、メインメソッド、公平かどうかチェックするメソッド、標準入力を取るメソッドの3つ。
def main
a, b, c = read_nums
puts is_fair?(a, b, c)
end
def is_fair?(a, b, c)
(a + b + c) / 2.0 == c ? "Yes" : "No"
end
def read_nums
gets.split.map(&:to_i).sort
end
main
通った!!!
●リファクタリング/別アプローチ
あまり思いつかないので割愛。
●他の方の回答例
あ…。そうか、はじめにソートしちゃってるから、a + b == c
これをすれば良いのか。2で割る必要とか無かった涙。
x.pop==x.sum
というのが面白かった!
まずpop
というメソッドを初めて知ったけど、3つの数字を配列に入れてxで取ってきてsort
しておいて、x.pop
で末尾の要素1つ=一番大きい数字を取る。で、残った2つの要素の合計がx.sum
で出せるので、それらが等しいかどうか判定すれば良い。なるほど〜。
●出てきたメソッド等
公式リファレンスを見る訓練。
■振り返りなど
- 足して2で割る、という序盤のアイデアに囚われて
a + b == c
で済むことに気が付かなかったのが悔しい。 - 新たに
pop
メソッドを知れて良かった。知らないメソッドがまだまだ沢山ある。