コンテンツへスキップ

【Ruby基礎】AtCoder Beginner Contest 050 A – Addition and Subtraction Easy

  • by

INDEX

■はじめに

Rubyの基礎的な問題をたくさん解くことで基本的な考え方やメソッドの使い方を定着させたい。
基本的にはAtCoderというプログラミングコンテスト(競技プログラミング)の過去問を使う。(AtCoderは難易度が分かれており、難易度の低いA問題かB問題を解いていく)

(5/23時点の方針)
メソッドの切り分け方や値の受け渡しを練習するために、コード長の短さについては気にせずに書くことにする。

■問題

●出典

AtCoder Beginner Contest 050のA問題
https://atcoder.jp/contests/abc050/tasks/abc050_a

●問題文

joisinoお姉ちゃんは、A op B という式の値を計算したいと思っています。 ここで、A,B は整数で、op は、+ または - の記号です。 あなたの仕事は、joisinoお姉ちゃんの代わりにこれを求めるプログラムを作ることです。

●制約

  • 1≦A,B≦10^9
  • op は、+ または - の記号である。

●入力

入力は以下の形式で標準入力から与えられる。

A op B

●出力

式の値を出力せよ。

■回答

●愚直に書く

opが+-かで条件分岐すれば良いか?
あ、opだけ整数じゃないからgets.split.map(&:to_i)が使えないのか…!

a, op, b = gets.split
if op == "+"
  puts a.to_i + b.to_i
else
  puts a.to_i - b.to_i
end

通った!
もっと綺麗にできそう。
とりあえず変数を追加してto_iの重複をなくすか。

a, op, b = gets.split
a_i = a.to_i
b_i = b.to_i
if op == "+"
  puts a_i + b_i
else
  puts a_i - b_i
end

全体のコード長は長くなったけど見やすくはなった、かな…?

●メソッド化して書く

メソッドを作る練習のために、あえてそういう書き方をする。

メソッドにしようとするとうまくいかない…。
下記はエラーになる。

def main
  a = read_nums[0].to_i
  op = read_nums[1]
  b = read_nums[2].to_i
  puts a
end

def calculation(a, b, op)
  op == "+" ? a + b : a - b
end

def read_nums
  gets.split
end

main

read_numsを3回呼び出してるのがダメっぽいけど改善方法がパッと思い浮かばないな〜。

あ〜〜〜そうだ、メインメソッドで一回別の変数に入れればread_numsの参照は一度で済むのか。これ何回かやったな…汗。
忘れていたことをもう一度できたので良しとしよう。

def main
  nums = read_nums
  a = nums.slice(0).to_i
  op = nums.slice(1)
  b = nums.slice(2).to_i
  puts calculation(a, b, op)
end

def calculation(a, b, op)
  op == "+" ? a + b : a - b
end

def read_nums
  gets.split
end

main

通った!
変数の名前はちょっと改善の余地がありそうだが…。

●リファクタリング/別アプローチ

三項演算子。

a, op, b = gets.split
a_i = a.to_i
b_i = b.to_i
puts op == "+" ? a_i + b_i : a_i - b_i

通った!

●他の方の回答例

トップの回答が衝撃的な短さだった笑。

p eval *$<

下記くらいのほうが今の自分には良いかも↓

p eval gets.chomp

evalはAtCoderでよく見かけつつスルーしてたのでここで一度ちゃんと調べてみる。

eval(expr) -> object
文字列 expr を Ruby プログラムとして評価してその結果を返します。]
Kernel.#evalより)

つまり今回で言うと、gets.chompして取得した"5 + 2"みたいな整数のカタマリをそのまま5 + 2として計算してくれるってことか。めちゃくちゃ便利…!今回の問題はevalを使うというのが最低条件と言える。

●出てきたメソッド等

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

■振り返りなど

  • 今までスルーしていたevalについて少しわかったので良かった。使いこなせるようになりたい。
  • メソッド化の方も手こずってしまったけど、その分練習する意味がある回だった。